jrswizzle icon indicating copy to clipboard operation
jrswizzle copied to clipboard

Result of invocation in block is freed before it can be used

Open JetForMe opened this issue 5 years ago • 4 comments

I attempted to swizzle the class method JSONObjectWithData:options:error: like this:

+ (void)
load
{
    static dispatch_once_t      sInitToken;
    dispatch_once(&sInitToken,
    ^{
        __block NSInvocation* invocation = nil;
        NSError* err = nil;
        invocation = [self jr_swizzleClassMethod: @selector(JSONObjectWithData:options:error:)
                            withBlock:
                            ^(id inObj, NSData* inData, NSJSONReadingOptions inOptions, NSError** outError)
                            {
                                NSLog(@"before %@", inObj);
                                
                                NSInvocation* inv = [invocation copy];
                                
                                [inv setArgument: &inData atIndex: 2];
                                [inv setArgument: &inOptions atIndex: 3];
                                [inv setArgument: &outError atIndex: 4];
                                
                                [inv invokeWithTarget: inObj];
                                
                                id ret = nil;
                                [inv getReturnValue: &ret];
                                
                                NSLog(@"after %@", inObj);
                                
                                return ret;
                            }
                            error: &err];
            if (invocation == nil)
            {
                NSLogDebug(@"Error swizzling NSJSONSerialization: %@", err);
            }
    });
}

But unfortunately this doesn't seem to work, as the returned dictionary gets released before a later call to objc_retainAutoreleasedReturnValue() deep inside iOS, causing a crash. Enabling Zombie objects shows:

*** -[__NSDictionaryI retain]: message sent to deallocated instance 0x600002611440

JetForMe avatar Feb 27 '19 01:02 JetForMe

Interestingly, doing the same thing with regular methods works fine. I wonder if this is an ARC bug.

JetForMe avatar Feb 27 '19 02:02 JetForMe

Have you found the solution, sir?

zhongshucheng avatar Apr 18 '20 12:04 zhongshucheng

Wow, sorry, I can't even remember why I wrote this code.

JetForMe avatar Apr 18 '20 13:04 JetForMe

I wrote this code was for testing in my script. I just found the invocation won't be released if I used a property to hold it. So it is not a problem now. Thanks anyway.

zhongshucheng avatar Apr 20 '20 02:04 zhongshucheng