2009-04-17 33 views
5

Tôi đang tìm cách theo dõi một số khó khăn để tìm rò rỉ bộ nhớ trong chương trình iPhone của mình. Tôi đang chạy một thử nghiệm nhanh trên một ứng dụng mà rò rỉ một đối tượng NSString với mã cố ý -incorrect- sau:Nhận biết tiện ích dòng lệnh 'rò rỉ' để tìm rò rỉ bộ nhớ

-(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; 
} 

Sau khi chạy rò rỉ về quá trình ID của ứng dụng, tôi đưa ra như sau:

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  ............... 

Bây giờ, chúng ta đều biết nơi bị rò rỉ. Đó không phải là điểm của bài tập này, ít nhất là đối với tôi. Tôi đang cố gắng để nhận ra làm thế nào để làm cho tinh thần của đầu ra này. Tôi đang được thông báo rằng có 3 rò rỉ.

Chúng là các đối tượng được đặt tại địa chỉ bộ nhớ 0x163b50, 0x178190, 0x178210. Việc triển khai của họ là trong các khung công tác của Apple, chứ không phải mã của tôi - theo 'rò rỉ'. Trong một ví dụ tầm thường như sau, việc tìm ra chỗ rò rỉ không khó. Tuy nhiên, trong một ứng dụng với 500K dòng mã, tôi thấy đầu ra từ rò rỉ ở đây vô dụng.

Tôi đang làm gì sai và làm cách nào tôi có thể hiểu được đầu ra này để giúp tôi tìm ra thủ phạm trong mã mà tôi đã viết để làm sạch rò rỉ bộ nhớ của mình?

Xin lưu ý rằng chủ đề này không nên chủ trương việc sử dụng Dụng cụ hoặc Máy phân tích tĩnh của Clang. Tôi đã dọn dẹp tất cả các rò rỉ bộ nhớ mà Clang Static Analyzer đã báo cáo với tôi. Nhạc cụ cồng kềnh và không mang tính thông tin cho tôi. Tôi nhận được rất nhiều báo cáo về rò rỉ, không có dấu vết ngăn xếp nào hiển thị quay trở lại mã của riêng tôi - mặc dù tôi chắc chắn rằng (các) rò rỉ thực sự nằm trong mã của tôi. Tôi muốn tìm hiểu cách sử dụng công cụ rò rỉ dòng cmd tại đây.

Cảm ơn tất cả.

EDIT: Ngay cả sau khi bỏ ghi chú các dòng để làm sạch rò rỉ, tiện ích 'rò rỉ' còn than phiền hơn khi có rò rỉ. Foundation/Cocoa có bị rò rỉ nhiều như thế từ một ví dụ tầm thường như vậy không? Điều này xảy ra sau khi bỏ ghi chú giải phóng cho chuỗi thử nghiệm ở trên:

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  ........`[email protected] 
    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.... 
+0

đây có phải là ứng dụng mac hoặc ứng dụng iphone không? bạn có thể sử dụng nhị phân rò rỉ từ mac trên iphone không? –

Trả lời

4

Không có dấu vết ngăn xếp nào trong kết quả bạn đã hiển thị. Các địa chỉ bạn thấy là các địa chỉ riêng của các đối tượng, không phải là các con trỏ hàm và các số hex bên cạnh các ký tự dấu chấm câu đơn giản là kết xuất dữ liệu hex.

Để tìm ra nơi các đối tượng được phân bổ từ, thiết MallocStackLogging trong môi trường rò rỉ của:

% MallocStackLogging=1 leaks … 

Bạn cũng có thể muốn sử dụng tùy chọn -nocontent, mà sẽ ngăn chặn các bãi chứa hex. Không sử dụng tất cả các thời gian, tuy nhiên: Đôi khi các bãi chứa hex có chứa một đầu mối có giá trị.

Ngoài ra, rò rỉ không nhất thiết phải cho bạn biết rằng bạn có ba rò rỉ; chính xác, nó cho bạn biết rằng bạn có ba đối tượng bị rò rỉ . Các rò rỉ cố ý bạn cho thấy sản xuất chỉ có một đối tượng bị rò rỉ, nhưng một rò rỉ khác nhau (chẳng hạn như trong một vòng lặp hoặc thường xuyên gọi là phương pháp) có thể bị rò rỉ nhiều đối tượng.

Chỉnh sửa: BTW, một số rò rỉ đó là từ SIMBL hoặc một hoặc nhiều plugin SIMBL của bạn. Tắt SIMBL và bất kỳ trình quản lý nhập liệu nào khác trước khi tìm kiếm bị rò rỉ. Hãy nhớ rằng, mã đó chạy trong quá trình của bạn; hơn nữa, rò rỉ không quan tâm mã của ai được cấp phát hoặc rò rỉ bộ nhớ, chỉ có nó bị rò rỉ, vì vậy nó sẽ hiển thị đối tượng bị rò rỉ bất kể ai đã cấp hoặc rò rỉ nó.

+0

Cảm ơn Peter. Tôi không có ý tưởng với SIMBL, nhưng tôi sẽ tìm nó. –

1

Ví dụ này, rò rỉ báo cáo 3 rò rỉ với tổng số 128 byte. Việc giải thích nên thực hiện như sau:

1), bạn đang bị rò rỉ một NSMutableString mà dường như được thực hiện trong nội bộ như NSCFDictionary với tổng số 64 byte

2) bạn đang bị rò rỉ Kiểm tra 1 với tổng số 32 byte

3), bạn đang bị rò rỉ \ nTesting 2 với tổng số 32 byte

này cần được bởi vì nếu bạn không phát hành NSMutableString của bạn, không ai trong số các đối tượng (chuỗi trong trường hợp này) thuộc cấu trúc dữ liệu NSCFDictionary sẽ được phát hành: chúng được giữ lại mỗi lần bạn sử dụng phương thức appendString. Khi bạn phát hành NSMutableString, tất cả đối tượng bên trong NSCFDictionary sẽ tự động được phát hành, cùng với chính NSCFDictionary.

Từ các tài liệu của Apple (http://developer.apple.com/iPhone/library/documentation/Performance/Conceptual/ManagingMemory/Articles/FindingLeaks.html):

Nếu một đối tượng Cocoa được autoreleased mà không có một hồ bơi autorelease tại chỗ, Xcode sẽ gửi một tin nhắn cho giao diện điều khiển cảnh báo bạn rằng đối tượng chỉ được rò rỉ. Ngay cả khi bạn không viết một ứng dụng Cocoa, có thể thấy cùng một kiểu cảnh báo console này.Việc thực hiện nhiều lớp Cacao được dựa trên các loại Core Foundation. Nếu ứng dụng của bạn sử dụng Core Foundation, có thể các rò rỉ đang xảy ra do các cuộc gọi đến khung công tác đó.

Để tìm rò rỉ bộ nhớ thuộc loại này, hãy sử dụng trình gỡ rối để đặt điểm ngắt trên hàm _NSAutoreleaseNoPool. Hàm này được khai báo trong NSDebug.h trong khung Foundation. Khi trình gỡ lỗi đạt đến chức năng đó, bạn sẽ có thể xem xét việc thu thập dữ liệu ngăn xếp và xem đoạn mã nào đã gây ra rò rỉ.

2

Tôi nghĩ lý do bạn thấy điều này trong rò rỉ là vì appendString đang sử dụng autorelease nội bộ. Các hồ bơi autorelease không được bỏ đi cho đến khi 'sự kiện' tiếp theo. Về cơ bản, tôi nghĩ rằng mẫu quá đơn giản để hiển thị chính xác những gì đang diễn ra.

Tôi có thể thoát khỏi cơ sở ở đây, nhưng tôi sẽ thử gói mã của bạn trong một nhóm tự động phát hiện để xem những thay đổi nào.

-(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 
}