2013-07-20 2 views
1

У меня есть класс, в котором копия NSString и print's хранятся в количестве и адресе.@property копия и ручное управление памятью с пулом автозапуска

@interface TestStringPointer : NSObject 

@property (copy) NSString *stringTest; 

- (void)printPointer; 

@end 

@implementation TestStringPointer 

- (void)printPointer { 
    NSLog(@"PrintPointer:%p\n RetainCount:%lu", _stringTest, [_stringTest retainCount]); 
} 

@end 

В моей основной функции я провел небольшое расследование по указателю String и столкнулся с проблемой.

int main(int argc, const char * argv[]) 
{ 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    TestStringPointer *test = [[TestStringPointer alloc] init]; 

    NSString *myString = [NSString stringWithUTF8String:"Hello World"]; 
    NSLog(@"MyString: %p \n RetainCount:%lu", myString, [myString retainCount]); 

    [test setStringTest:myString]; 
    [test printPointer]; 
    [myString release]; 
    [pool drain]; 

    while (1) { 
    [test printPointer]; 
    } 

    return 0; 
} 

Когда я отлаживаю приложение, он сбрасывает 3-е время через цикл while (количество раз в цикле меняется). Я понимаю, что копия не возникает, потому что строка не изменена. После того, как он выпущен в основном, я бы ожидал, что он вернется к 1.
1) Если объект не автореализован, все равно влияет на пул автозаполнения?
2) Не имело ли максимальное количество удержаний, чтобы предотвратить утечку объекта в пуле, или это означает его удаление?
3) Не должна ли копия в какой-то момент вмешаться и на самом деле сделала копию до ее удаления?

StringPointerTest [2253: 303] MyString: 0x100100f60 RetainCount: 1
StringPointerTest [2253: 303] PrintPointer: 0x100100f60 RetainCount: 2
StringPointerTest [2253: 303] PrintPointer: 0x100100f60 RetainCount: 1152921504606846975
StringPointerTest [2253: 303] PrintPointer: 0x100100f60 RetainCount: 1152921504606846975

Если я изменить основной и удалить пул

int main(int argc, const char * argv[]) 
{ 

    TestStringPointer *test = [[TestStringPointer alloc] init]; 

    NSString *myString = [NSString stringWithUTF8String:"Hello World"]; 
    NSLog(@"MyString: %p \n RetainCount:%lu", myString, [myString retainCount]); 

    [test setStringTest:myString]; 
    [test printPointer]; 
    [myString release]; 

    while (1) { 
    [test printPointer]; 
    } 

    return 0; 
} 

Все правильно ... Навсегда ...

StringPointerTest [423: 303] MyString: 0x10010a670 RetainCount: 1
StringPointerTest [423: 303] PrintPointer: 0x10010a670 RetainCount: 2
StringPointerTest [423: 303] PrintPointer: 0x10010a670 RetainCount: 1
...

ответ

0

ошибка заключается в том, когда вы отпускаете myString. Это неверно, потому что stringWithUTF8String возвращает строку с автореализацией (помните, что каждый метод имеет автореализованную версию: статический метод и неавтореализованную версию: init или initWithSomething:). Поэтому, когда пул авторесурсов истощается, myString удержание счета идет к нулю, и объект освобождается (возможно, позже вы точно не знаете, когда тот факт, что он сбой на третьей итерации цикла, случайный).

Вы решили проблему, позвонив по телефону alloc + initWithUTF8String: вместо stringWithUTF8String:. Тот факт, что вы видите невероятно высокий показатель удержания, просто зависит от того, что память была освобождена и, возможно, написана снова, прежде чем объект действительно освободится, это всего лишь ошибка, вы больше не владеете объектом.

+0

Причина, по которой существует высокая степень сохранения, заключается в том, что объект может быть сохранен и автореализован любое количество раз любой функцией API, которую он вызывает. Счет сохранения обычно никогда не бывает полезным. – newacct