ARC下的dataWithBytesNoCopy导致内存泄漏?

时间:2015-08-20 17:46:00

标签: ios objective-c memory-leaks

我有NSData个实例,但我只对给定偏移量的数据感兴趣。我考虑过使用dataWithBytesNoCopy:length:freeWhenDone:来防止复制数据,但我发现我并没有真正意识到发生了什么:

self.data = [NSMutableData dataWithBytesNoCopy:(void *)(self.data.bytes + offset)
                                        length:self.data.length - offset
                                  freeWhenDone:NO];

我不再有指向数据块开头的指针,所以我不确定ARC如何处理这个问题。数据块现在指向同一个块,但不是在开头。当我完成时,ARC会取消整个块吗?偏移之前的数据是否保持在同一时间?

2 个答案:

答案 0 :(得分:0)

你不是泄漏内存,但更糟糕的是,引用释放的内存:新的 08-20 13:57:40.821 7257-7257/? D/dalvikvm﹕ Late-enabling CheckJNI 08-20 13:57:41.425 7257-7257/com.example.abdullah.deneme I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getChangingConfigurations, referenced from method android.support.v7.internal.widget.TintTypedArray.getChangingConfigurations 08-20 13:57:41.429 7257-7257/com.example.abdullah.deneme W/dalvikvm﹕ VFY: unable to resolve virtual method 406: Landroid/content/res/TypedArray;.getChangingConfigurations ()I 08-20 13:57:41.433 7257-7257/com.example.abdullah.deneme D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002 08-20 13:57:41.437 7257-7257/com.example.abdullah.deneme I/dalvikvm﹕ Could not find method android.content.res.TypedArray.getType, referenced from method android.support.v7.internal.widget.TintTypedArray.getType 08-20 13:57:41.441 7257-7257/com.example.abdullah.deneme W/dalvikvm﹕ VFY: unable to resolve virtual method 428: Landroid/content/res/TypedArray;.getType (I)I 08-20 13:57:41.445 7257-7257/com.example.abdullah.deneme D/dalvikvm﹕ VFY: replacing opcode 0x6e at 0x0002 08-20 13:57:41.561 7257-7257/com.example.abdullah.deneme D/dalvikvm﹕ GC_FOR_ALLOC freed 147K, 6% free 3684K/3892K, paused 34ms, total 40ms 08-20 13:57:41.605 7257-7257/com.example.abdullah.deneme D/dalvikvm﹕ GC_FOR_ALLOC freed 4K, 6% free 3901K/4116K, paused 16ms, total 18ms 08-20 13:57:41.693 7257-7257/com.example.abdullah.deneme I/dalvikvm-heap﹕ Grow heap (frag case) to 6.286MB for 2536932-byte allocation 08-20 13:57:41.701 7257-7268/com.example.abdullah.deneme D/dalvikvm﹕ GC_FOR_ALLOC freed <1K, 4% free 6378K/6596K, paused 5ms, total 5ms 08-20 13:57:41.725 7257-7257/com.example.abdullah.deneme D/AndroidRuntime﹕ Shutting down VM 08-20 13:57:41.729 7257-7257/com.example.abdullah.deneme W/dalvikvm﹕ threadid=1: thread exiting with uncaught exception (group=0xa4d2db20) 08-20 13:57:41.733 7257-7257/com.example.abdullah.deneme E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: com.example.abdullah.deneme, PID: 7257 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.abdullah.deneme/com.example.abdullah.deneme.MainActivity}: java.lang.RuntimeException: Don't call setOnClickListener for an AdapterView. You probably want setOnItemClickListener instead at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233) at android.app.ActivityThread.access$800(ActivityThread.java:135) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5001) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.RuntimeException: Don't call setOnClickListener for an AdapterView. You probably want setOnItemClickListener instead at android.widget.AdapterView.setOnClickListener(AdapterView.java:774) at com.example.abdullah.deneme.MainActivity.onCreate(MainActivity.java:28) at android.app.Activity.performCreate(Activity.java:5231) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)             at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)             at android.app.ActivityThread.access$800(ActivityThread.java:135)             at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)             at android.os.Handler.dispatchMessage(Handler.java:102)             at android.os.Looper.loop(Looper.java:136)             at android.app.ActivityThread.main(ActivityThread.java:5001)             at java.lang.reflect.Method.invokeNative(Native Method)             at java.lang.reflect.Method.invoke(Method.java:515)             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)             at dalvik.system.NativeStart.main(Native Method) 08-20 13:57:45.065 7257-7257/com.example.abdullah.deneme I/Process﹕ Sending signal. PID: 7257 SIG: 9 Process: com.example.abdullah.deneme, PID: 7257 java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.abdullah.deneme/com.example.abdullah.deneme.MainActivity}: java.lang.RuntimeException: Don't call setOnClickListener for an AdapterView. You probably want setOnItemClickListener instead at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2184) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233) at android.app.ActivityThread.access$800(ActivityThread.java:135) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:136) at android.app.ActivityThread.main(ActivityThread.java:5001) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:515) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) at dalvik.system.NativeStart.main(Native Method) Caused by: java.lang.RuntimeException: Don't call setOnClickListener for an AdapterView. You probably want setOnItemClickListener instead at android.widget.AdapterView.setOnClickListener(AdapterView.java:774) at com.example.abdullah.deneme.MainActivity.onCreate(MainActivity.java:28) at android.app.Activity.performCreate(Activity.java:5231) at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1087) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2148)             at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2233)             at android.app.ActivityThread.access$800(ActivityThread.java:135)             at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1196)             at android.os.Handler.dispatchMessage(Handler.java:102)             at android.os.Looper.loop(Looper.java:136)             at android.app.ActivityThread.main(ActivityThread.java:5001)             at java.lang.reflect.Method.invokeNative(Native Method)             at java.lang.reflect.Method.invoke(Method.java:515)             at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)             at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)             at dalvik.system.NativeStart.main(Native Method) 实例将指向由原始NSData维护的存储。但是,一旦分配了新实例,原始实例将被释放。从那时起,新NSData包含一个悬空指针。访问数据实际上是未定义的行为。

您应该创建字节的副本:

NSData

这样你就可以确定新的self.data = [self.data subdataWithRange:(NSRange){ offset, self.data.length - offset }]; 实际上拥有它所指向的字节。

答案 1 :(得分:0)

ARC可以处理涉及指向对象的指针的某些情况,但存在限制。阅读Clang documentation on interior pointers。 HTH