Jules
Jules

Reputation: 7766

Obj-C, Reference-counted object is used after it is released?

I`m getting the following warning.

Reference-counted object is used after it is released

ARC is enabled for this file.

I have not converted my app to use ARC and don`t have an proper understanding of it at this time. However, at a glance I am puzzled why this code should have a problem (its from a library), I mean I know autorelease should not be used here?

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    id uuid = [defaults objectForKey:@"uniqueID"];
    if (uuid)
        uniqueID = (NSString *)uuid;
    else {
        CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
        uniqueID = (__bridge NSString *)cfUuid;
        CFRelease(cfUuid);
        [defaults setObject:uniqueID forKey:@"uniqueID"]; // warning here
    }

EDIT @JohnCalsbeek, @epatel, @Chuck Thanks, I've just tried that and I get a new warning on CFStringRef cfUuid line, saying potential leak.

Heres the full file https://github.com/MugunthKumar/MKStoreKit/blob/master/MKSKProduct.m

Upvotes: 1

Views: 923

Answers (4)

Pochi
Pochi

Reputation: 13459

Try this one, srry for the miss understanding haha

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
id uuid = [defaults objectForKey:@"uniqueID"];

if (uuid)
    uniqueID = [NSString stringWithString:(NSString *)uuid];
else {
    CFUUIDRef temp = CFUUIDCreate(NULL);
    CFStringRef cfUuid = CFUUIDCreateString(NULL, temp);
    uniqueID = [NSString stringWithString:(__bridge NSString*) cfUuid];
    CFRelease(cfUuid);
    CFRelease(temp);

    [defaults setObject:uniqueID forKey:@"uniqueID"]; // warning here
}

Upvotes: 2

John Calsbeek
John Calsbeek

Reputation: 36497

A __bridge cast is not a transfer of ownership. uniqueID does not become an owning reference, and so becomes invalid at the line with the warning. You can either use __bridge_transfer (which transfers ownership to the Objective-C reference) and remove your CFRelease call, or change the call to CFRelease to be after the call to -setObject:forKey:.

Upvotes: 2

Chuck
Chuck

Reputation: 237010

You create a string with CFUUIDCreateString(NULL, CFUUIDCreate(NULL). Then you assign uniqueID to also refer to that string. Then you release the string with CFRelease(cfUuid). Then you use the string (as uniqueID) on the next line. That's invalid, because you just released it.

Upvotes: 1

epatel
epatel

Reputation: 46051

I believe it can be this line that doesn't do what you expect

uniqueID = (__bridge NSString *)cfUuid;

It is a simple cast and the next line will actually release both cfUuid and uniqueID (which actually is the same object).

So I'd change the order of the following lines to

[defaults setObject:uniqueID forKey:@"uniqueID"]; // warning here
CFRelease(cfUuid);

Upvotes: 1

Related Questions