1

I have this crash:objc_retains in my code.

My project is ARC.

Then I add a symbolic breakpoint whose Symbol is "objc_retain" and Module is "libobjc.A.dylib".

And I found it finally crash at this file of "BlocksKit":

+ (void)associateCopyOfValue:(id)value withKey:(const char *)key {
    objc_setAssociatedObject(self, key, value, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

If I didn't use the function "performBlock..." of "BlocksKit", it works:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    //if I delete the code below, it works
    [self performBlock:^(id sender) {
        NSLog(@"hit");
    } afterDelay:0.3f];
}

I had debug this for several days, but I can't solve this problemT_T Could anyone help me?

This is my project: http://www.mediafire.com/download/hppnt7k491y5f1k/QQSDKDemo.zip

This is the call stack:

callStack :(
    0   QQSDKDemo                           0x00008b8e +[NSObject(A2BlockDelegateBlocksKitPrivate) bk_accessorsMap] + 142
    1   QQSDKDemo                           0x00008de1 +[NSObject(A2BlockDelegateBlocksKitPrivate) registerDynamicDelegateNamed:forProtocol:] + 81
    2   QQSDKDemo                           0x00009f58 +[MFMailComposeViewController(BlocksKit) load] + 136
    3   libobjc.A.dylib                     0x019657f5 call_load_methods + 437
    4   libobjc.A.dylib                     0x01967de5 load_images + 133
    5   ???                                 0x8fef0c32 0x0 + 2414808114
    6   ???                                 0x8feff252 0x0 + 2414867026
    7   ???                                 0x8feff0ba 0x0 + 2414866618
    8   ???                                 0x8fef0e05 0x0 + 2414808581
    9   ???                                 0x8fef4adb 0x0 + 2414824155
    10  ???                                 0x8fef0376 0x0 + 2414805878
    11  ???                                 0x8fef0077 0x0 + 2414805111
)
Aevit
  • 21
  • 5
  • It looks like that code is just associating a copy of the block with self (similar to creating an ivar ref). . . it should be ok. Can you print a stack trace when it crashes? (http://stackoverflow.com/questions/220159/how-do-you-print-out-a-stack-trace-to-the-console-log-in-cocoa) and post the stack trace. – Jasper Blues Oct 16 '13 at 08:05
  • Thanks for your reply! I've post the stack trace. – Aevit Oct 17 '13 at 02:37

2 Answers2

0

I'm not sure why this is happening (it looks OK from a distance), however there's plenty of ways you could work around it.

How about, instead using:

[self performSelector:@selector(doSomething) withObject:nil afterDelay:0.3];

Otherwise perhaps raise an issue with the authors of BlocksKit?

Jasper Blues
  • 28,258
  • 22
  • 102
  • 185
0

I've taken a look at your project. It's weirder than it seems. Some observations:

  1. After removing QQSDKCall.m from the target, it no longer crashes. However, QQSDKCall is not currently used in the rest of the app, so this is a little weird. Also, QQSDKCall is the only code that uses the Tencent SDKs.
  2. After removing QQSDKCall.m, putting the line [TencentOAuth class]; anywhere into the code (even code that is not called, like -[ViewController didReceiveMemoryWarning]) causes it to crash again. This may be related to how the linker will not link classes that are not referenced in other code. ("Unknown class <MyClass> in Interface Builder file" error at runtime)
  3. To confirm, after removing QQSDKCall.m and not putting in that line of code, adding the compiler flags -all_load -ObjC to force the linker to link all files also causes it to crash.

Conclusion: It crashes when run after the Tencent libraries are linked. Your project doesn't have the source of those libraries, so it's hard to speculate on what's happening there. I've found that copying the implementation of performBlock:afterDelay: into the ViewController class seems to make it not crash. So perhaps the Tencent library contains its own category of NSObject implementing a method named performBlock:afterDelay:. (The order in which two categories are loaded is indeterminate.) And perhaps their implementation returns void instead of id like the BlocksKit one. So when Xcode (which thinks you are calling the BlockKit one) expects an id return and tries to retain it, it is actually garbage and retaining it crashes.

Community
  • 1
  • 1
newacct
  • 119,665
  • 29
  • 163
  • 224