Осмысление утилиты командной строки 'leaks' для обнаружения утечек памяти - PullRequest
5 голосов
/ 17 апреля 2009

Я работаю над обнаружением утечек памяти в моей программе для iPhone. Я запускаю быстрый тест на приложение, которое пропускает объект NSString со следующим намеренно -неверным кодом:

-(void)applicationDidFinishLaunching:(NSNotification *)notification;
{
    NSMutableString *test = [[NSMutableString alloc] init];
    [test appendString:@"Testing 1"];
    [test appendString:@"\nTesting 2"];
    NSLog(@"%@", test);

    // Uncomment the following line to release the
    // string and clean up your leak.
    // [test release], test = nil;
}

После запуска утечек по идентификатору процесса приложения у меня появляется следующее:

sf$ leaks 3951
Process 3951: 9988 nodes malloced for 1260 KB
Process 3951: 3 leaks for 128 total leaked bytes.
Leak: 0x163b50  size=64 instance of 'NSCFDictionary', type ObjC, implemented in Foundation  
    0xa07e0720 0x01001080 0x0000000a 0x00000010      .~.............
    0x0000000a 0x0000000c 0x0000000b 0x00000000     ................
    0x00000000 0x00000015 0xa1b1c1d3 0x00163b90     .............;..
    0x00163bd0 0x00000000 0x00000000 0x00000000     .;..............
Leak: 0x178190  size=32 string 'Testing 1
Testing 2'
Leak: 0x178210  size=32 instance of 'NSCFString', type ObjC, implemented in CoreFoundation  
    0xa02e24a0 0x010007ad 0x00178190 0x00000013     .$..............
    0x00000020 0x00000200 0x00000000 0x00000000      ...............

Теперь мы все знаем, где находится утечка. Это не главное в этом упражнении, по крайней мере для меня. Я пытаюсь понять, как понять этот вывод. Мне говорят, что есть 3 утечки.

Это объекты, которые расположены по адресам памяти 0x163b50, 0x178190, 0x178210. Их реализация в рамках Apple, а не в моем коде - согласно «утечкам». В тривиальном примере, таком как следующий, найти утечку не сложно. Однако в приложении с 500K-строками кода вывод утечек здесь бесполезен.

Что я делаю не так и как я могу понять этот вывод, чтобы помочь мне найти виновника в коде, который я написал для устранения утечек памяти?

Обратите внимание, что эта ветка не должна пропагандировать использование Instruments или Clang Static Analyzer. Я убрал все утечки памяти, о которых мне сообщил Clang Static Analyzer. Инструменты раздуты и неинформативны для меня. Я получаю массу отчетов об утечках, ни один из которых не показывает трассировки стека, возвращаясь к моему собственному коду - хотя я уверен, что утечки действительно есть в моем коде. Я хотел бы выяснить, как использовать инструмент утечки строки cmd здесь.

Спасибо всем.

РЕДАКТИРОВАТЬ : Даже после раскомментирования линий для устранения утечек утилита «утечки» жалуется даже больше, чем при утечках. Является ли Foundation / Cocoa настолько утекшим из такого тривиального примера? Это происходит после раскомментирования выпуска для тестовой строки выше:

sf$ leaks 4383
Process 4383: 9890 nodes malloced for 1255 KB
Process 4383: 7 leaks for 560 total leaked bytes.
Leak: 0x163920  size=176    instance of 'NSPathStore2', type ObjC, implemented in Foundation    
    0xa07e2ae0 0x04f00000 0x0055002f 0x00650073     .*~...../.U.s.e.
    0x00730072 0x0073002f 0x002f0066 0x0069004c     r.s./.s.f./.L.i.
    0x00720062 0x00720061 0x002f0079 0x00700041     b.r.a.r.y./.A.p.
    0x006c0070 0x00630069 0x00740061 0x006f0069     p.l.i.c.a.t.i.o.
    0x0020006e 0x00750053 0x00700070 0x0072006f     n. .S.u.p.p.o.r.
    0x002f0074 0x00490053 0x0042004d 0x002f004c     t./.S.I.M.B.L./.
    0x006c0050 0x00670075 0x006e0069 0x002f0073     P.l.u.g.i.n.s./.
    0x00650054 0x006d0072 0x006e0069 0x006c0061     T.e.r.m.i.n.a.l.
    ...
Leak: 0x163350  size=160    instance of 'NSPathStore2', type ObjC, implemented in Foundation    
    0xa07e2ae0 0x04a00000 0x0055002f 0x00650073     .*~...../.U.s.e.
    0x00730072 0x0073002f 0x002f0066 0x0069004c     r.s./.s.f./.L.i.
    0x00720062 0x00720061 0x002f0079 0x00700041     b.r.a.r.y./.A.p.
    0x006c0070 0x00630069 0x00740061 0x006f0069     p.l.i.c.a.t.i.o.
    0x0020006e 0x00750053 0x00700070 0x0072006f     n. .S.u.p.p.o.r.
    0x002f0074 0x00490053 0x0042004d 0x002f004c     t./.S.I.M.B.L./.
    0x006c0050 0x00670075 0x006e0069 0x002f0073     P.l.u.g.i.n.s./.
    0x00650044 0x0069006c 0x00690063 0x0075006f     D.e.l.i.c.i.o.u.
    ...
Leak: 0x1635a0  size=64 instance of 'NSCFDictionary', type ObjC, implemented in Foundation  
    0xa07e0720 0x01001080 0x0000000a 0x00000010      .~.............
    0x0000000a 0x0000000c 0x0000000b 0x00000000     ................
    0x00000000 0x00000015 0xa1b1c1d3 0x001635e0     .............5..
    0x00163620 0x00000000 0x00000000 0x00000000      6..............
Leak: 0x163620  size=64 
    0xa02ed360 0x00160ee0 0x00163700 0xa02efc00     `........7......
    0x00000000 0x00000000 0x00163680 0x00000000     .........6......
    0x00000000 0x00000000 0x00163660 0xa02ed440     ........`6..@...
    0xa02ec1a0 0xa02f0420 0x00000000 0x00163660     .... ./.....`6..
Leak: 0x163680  size=48 instance of 'NSCFString', type ObjC, implemented in CoreFoundation  
    0xa02e24a0 0x0100078c 0x6d6f6323 0x6c65642e     .$......#com.del
    0x6f696369 0x61737375 0x69726166 0x6c65442e     icioussafari.Del
    0x6f696369 0x61537375 0x69726166 0x00000000     iciousSafari....
Leak: 0x163660  size=32 instance of 'NSCFString', type ObjC, implemented in CoreFoundation  
    0xa02e24a0 0x0200078c 0x6c65440f 0x6f696369     .$.......Delicio
    0x61537375 0x69726166 0x00000000 0x00000000     usSafari........
Leak: 0x160ee0  size=16 instance of 'NSCFString', type ObjC, implemented in CoreFoundation  
    0xa02e24a0 0x0100078c 0x362e3103 0x00000000     .$.......1.6....

Ответы [ 3 ]

4 голосов
/ 18 апреля 2009

В выводе, который вы показали, нет трассировки стека. Адреса, которые вы видите, являются собственными адресами объектов, а не указателями на функции, а шестнадцатеричные числа рядом с символами пунктуации - это просто шестнадцатеричный дамп данных.

Чтобы узнать, где был расположен объект из , установите MallocStackLogging в среде утечек:

% MallocStackLogging=1 leaks …

Вы также можете использовать опцию -nocontent, которая подавит шестнадцатеричный дамп. Однако не используйте это все время: иногда шестнадцатеричный дамп содержит ценную подсказку.

Кроме того, утечки не обязательно говорят вам, что у вас есть три утечки; если быть точным, это говорит вам, что у вас есть три утечка объектов . Преднамеренная утечка, которую вы продемонстрировали, приводит только к одному утечке объекта, но другая утечка (например, в цикле или часто вызываемом методе) может привести к утечке многих объектов.

Редактировать: Кстати, некоторые из этих утечек из SIMBL или одного или нескольких ваших плагинов SIMBL. Отключите SIMBL и любые другие хаки менеджера ввода перед поиском утечки. Помните, что код работает в вашем процессе; кроме того, для утечек не имеет значения, чей код выделил или просочился в память, только для того, чтобы он просочился, поэтому он покажет просочившийся объект независимо от того, кто выделил или утек.

2 голосов
/ 17 апреля 2009

Я думаю, причина того, что вы видите это в утечках, в том, что appendString использует autorelease для внутреннего использования. Пул авто-релиза не удаляется до следующего «события». В принципе, я думаю, что образец слишком прост, чтобы точно показать, что происходит.

Я мог бы быть далеко от базы, но я бы попробовал обернуть ваш код в пул авто-релиза, чтобы посмотреть, что изменится.

-(void)applicationDidFinishLaunching:(NSNotification *)notification;
{
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSMutableString *test = [[NSMutableString alloc] init];
    [test appendString:@"Testing 1"];
    [test appendString:@"\nTesting 2"];
    NSLog(@"%@", test);
    [test release], test = nil;
    [pool release] // this should drain the autorelease pool
}
1 голос
/ 17 апреля 2009

Для этого примера, утечки сообщают о 3 утечках в общей сложности 128 байтов. Интерпретация должна быть следующей:

1) у вас есть утечка NSMutableString, которая, по-видимому, реализована внутри как NSCFDictionary в общей сложности 64 байта

2) вы пропускаете тестирование 1 на общую сумму 32 байта

3) у вас есть утечка \ nTesting 2 для 32 байтов

Это должно быть потому, что если вы не освободите NSMutableString, ни один из объектов (в данном случае строк), принадлежащих структуре данных NSCFDictionary, не будет освобожден: они сохраняются при каждом использовании метода appendString. Когда вы освобождаете NSMutableString, все объекты внутри NSCFDictionary автоматически освобождаются вместе с самим NSCFDictionary.

Из документации Apple (http://developer.apple.com/iPhone/library/documentation/Performance/Conceptual/ManagingMemory/Articles/FindingLeaks.html):

Если объект Какао автоматически освобожден без установленного пула автоматического выпуска, XCode отправляет сообщение на консоль, предупреждая вас, что объект только протекает. Даже если вы не пишете приложение Какао, вы можете увидеть такой же тип предупреждения консоли. Реализация многих классов Какао основана на Базовых типах Основы. Если ваше приложение использует Core Foundation, возможно, что утечки происходят в результате обращений к этой платформе.

Чтобы найти утечки памяти этого типа, используйте отладчик для установки точки останова на функцию _NSAutoreleaseNoPool. Эта функция объявлена ​​в NSDebug.h в рамках Основы. Когда отладчик достигнет этой функции, вы сможете просмотреть обход стека и посмотреть, какой фрагмент кода вызвал утечку.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...