Объект с подсчетом ссылок используется после его освобождения - PullRequest
1 голос
/ 01 апреля 2012

Выполнение анализа кода проекта и получение сообщения « Объект с подсчетом ссылок используется после его освобождения » в строке [по умолчанию setObject: deviceUuid forKey: @ "deviceUuid"];

Я смотрел эту тему Obj-C, объект с подсчетом ссылок используется после его выпуска? Но решение не найдено.ARC отключен.

// Get the users Device Model, Display Name, Unique ID, Token & Version Number
UIDevice *dev = [UIDevice currentDevice];
NSString *deviceUuid;
if ([dev respondsToSelector:@selector(uniqueIdentifier)])
    deviceUuid = dev.uniqueIdentifier;
else {
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    id uuid = [defaults objectForKey:@"deviceUuid"];
    if (uuid)
        deviceUuid = (NSString *)uuid;
    else {
        CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
        deviceUuid = (NSString *)cfUuid;
        CFRelease(cfUuid);
        [defaults setObject:deviceUuid forKey:@"deviceUuid"];
    }
}

Пожалуйста, помогите найти причину.

Ответы [ 2 ]

4 голосов
/ 01 апреля 2012

Проблема здесь:

    CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
    deviceUuid = (NSString *)cfUuid;
    CFRelease(cfUuid);
    [defaults setObject:deviceUuid forKey:@"deviceUuid"];

Давайте рассмотрим, что это на самом деле делает:

    CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));

CFUUID создан (и просочился).CFStringRef создается и присваивается cfUuid.(Примечание: имя cfUuid подразумевает, что cfUuid является CFUUIDRef. Конечно, это не так; это CFStringRef.)

    deviceUuid = (NSString *)cfUuid;

Тот же самый CFStringRef тип приведен и назначенdeviceUuid.Это , а не новый экземпляр NSString или CFStringRef, это просто типографский набор того же экземпляра.

    CFRelease(cfUuid);

Вы освобождаете CFStringRef.Поскольку NSString указывает на тот же объект, вы также освобождаете его.

    [defaults setObject:deviceUuid forKey:@"deviceUuid"];

И здесь вы используете типизированный объект, который был выпущен ранее.

Самое простое исправление устаревшего указателяэто:

    CFStringRef cfUuid = CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
    deviceUuid = (NSString *)cfUuid;
    [defaults setObject:deviceUuid forKey:@"deviceUuid"];
    CFRelease(cfUuid);

Но этот код опасен, и вы уже знаете, почему: deviceUuid также недопустим.Но это не очевидно, так что вы можете покататься на нем позже.Кроме того, он не устраняет утечку CFUUID.

Чтобы исправить утечку CFStringRef, вы можете использовать это:

    deviceUuid = (NSString *)CFUUIDCreateString(NULL, CFUUIDCreate(NULL));
    [defaults setObject:deviceUuid forKey:@"deviceUuid"];
    [deviceUuid autorelease]; // or release, if you don't need it in code not
                              // included in your post

Однако это все равно не устраняет утечку CFUUID.

    CFUUIDRef cfuuid = CFUUIDCreate(NULL);
    deviceUuid = (NSString *)CFUUIDCreateString(NULL, cfuuid);
    CFRelease(cfuuid);
    [defaults setObject:deviceUuid forKey:@"deviceUuid"];
    [deviceUuid autorelease]; // or release, if you don't need it in code not
                              // included in your post
1 голос
/ 01 апреля 2012

Проблема здесь:

CFRelease(cfUuid); 

Вы не должны выпускать это, вы должны выпустить deviceUuid, когда вы закончите с этим.

...