Lời nói đầu; Đây không phải là một câu hỏi chung "Tôi có một ứng dụng khổng lồ với một sự rò rỉ". Đó là một vấn đề cụ thể về tính năng đếm tham chiếu tự động không hoạt động bình thường trong một ứng dụng demo gần như tầm thường, với mã nguồn đầy đủ, hoặc tạo mã nhị phân hoặc vấn đề trình biên dịch hoặc lỗi trong công cụ. (TLDR: Ồ. Trên thực tế là một điều kiện chủng tộc nhỏ lẻ)Một bộ nhớ Phantom bị rò rỉ với ARC trong XCode 4.5 nơi dealloc chắc chắn được gọi hoặc một vấn đề cụ?
Tôi bối rối bởi thực tế là danh sách "Phân bổ" của cụ đang hiển thị rò rỉ thể hiện, tôi có một thể hiện của lớp đó, chỉ một, và ARC đang gây ra phương thức dealloc được gọi và tôi biết nó đang được gọi vì có một thông điệp NSLog được in khi dealloc được thực hiện, nhưng nó vẫn xuất hiện trong danh sách rò rỉ trong Instruments.
KeepCount không bao giờ vượt quá 1. Nó không được giữ lại bởi bất cứ ai, và nó đang được dealloc'd, nhưng nó có vẻ như nó là một "rò rỉ" bởi vì nó hiển thị như một trường hợp hoạt động trong rò rỉ của Instrument.
Làm cách nào có thể?
Tôi vẫn đang học Objective-C với ARC, và vì vậy tôi nghĩ rằng tôi phải mắc một lỗi mới bắt đầu phổ biến. Đây là duy nhất của tôi init và dealloc đối tượng của tôi:
- (id) initWithMessage:(NSString*)messageForUser
{
self = [super init];
if (self)
{
_message = messageForUser;
NSLog(@"from constructor: %@",_message);
}
return self;
}
- (void)dealloc {
NSLog(@"Goodbye cruel world. One WPMyObject signing off.");
// [message release]; // ARC forbiddeth thee! Begone release.
_message = nil;
// [super dealloc]; // ARC forbiddeth explicit super dealloc
}
Chỉ cần để xem nếu tôi có thể, tôi cố gắng gọi [super dealloc]
trong phương thức dealloc, và ARC khối bạn với một lỗi, đó là rất tốt vì nó sẽ làm điều đó cho bạn. Tuy nhiên khi tôi viết phương pháp init của riêng tôi, nó không chặn tôi.
Khi tôi chạy chương trình bằng cách sử dụng "Chạy" trong XCode, tôi nhận được thông điệp NSLog "tạm biệt" độc ác, như tôi đã hi vọng, khi dealloc được chạy, nhưng tôi cũng nhận được bằng chứng cho thấy trường hợp vẫn tồn tại khi kết thúc chạy, khi phân tích dụng cụ sử dụng mẫu rò rỉ bộ nhớ được sử dụng:
Nếu tôi chạy mà không có mã tạo cá thể dưới đây, tôi chỉ nhận được một vài lỗ rò thư viện chuẩn, nhưng nếu tôi thêm mã này, rò rỉ xảy ra:
WPMyObject * myObject = [[WPMyObject alloc] initWithMessage: @"Hello World!\n" ];
Đây là những gì tôi thấy và nghĩ rằng tôi hiểu đang nói với tôi rằng trường hợp duy nhất của WPMyObject bị rò rỉ:
Mã nguồn đầy đủ mà là khá tầm thường (Mac OS X dòng lệnh ứng dụng nhỏ gọn sử dụng Objective-C và Foundation/Foundation.h
) là trên BitBucket. Nhấp vào this link để xem mã nguồn trong trình duyệt của bạn.
Đơn vị main.m chạy một đối tượng thử nghiệm tạo ra trường hợp duy nhất, bên trong một tuyên bố @autoreleasepool {...}
bối cảnh:
Nếu bạn muốn xem mã hoàn toàn tầm thường trên máy tính riêng của bạn, lấy nó như thế này :
hg clone https://bitbucket.org/wpostma/objectivecplaymac
cập nhật: Bạn có thể sửa chữa "rò rỉ" (có thể là một lỗi trong Instruments, hoặc kêu vang/llvm biên dịch lỗi, và không phải là một "rò rỉ thực") bằng cách thêm dòng mã này ngay trước khi số }
kết thúc hồ bơi tự động trả lời:
NSLog(@"Reached end of autorelease pool");
Đúng. Thêm thông điệp tường trình. "Rò rỉ" biến mất.Đây là XCode 4.5.2 (4G2008a) trên Mac OS X 10.7.5, chứa các công cụ Phiên bản 4.5 (xây dựng 4523).
Update2: Nó thực sự là một điều kiện đua đa tiến trình đơn giản. Đoạn mã dưới đây có vẻ là một lỗi hack-xây dựng một cách hợp lý. Nếu có một cách rõ ràng hơn để nói "chờ cho đến khi Nhạc được thực hiện với tôi, và sau đó thoát khỏi main()", đó có thể là một tính năng tương lai tốt đẹp, các kỹ sư của Apple. Một PROFILER_SYNC ("MESSAGE") macro mở rộng thành không có gì trong chế độ phát hành, nhưng trong quá trình xây dựng gỡ lỗi, gửi "MESSAGE" tới profiler .... Nó có thể rất tiện dụng.
int main(int argc, const char * argv[])
{
// This creates and cleans up an auto-release pool context.
@autoreleasepool {
foo(); // Microscopic amounts of debug code you want profiler to analyze go here.
#ifdef DEBUG
usleep(10000); // race condition prevention in debug builds, so Instruments can finish up.
#endif
}
#ifdef DEBUG
usleep(10000); // race condition prevention in debug builds, so Instruments can finish up.
#endif
return 0;
}
Một điều kiện chủng tộc giữa chủ đề heap-watch-thread và chủ đề chính của chương trình của tôi, về cơ bản? Bởi vì đó là hai chủ đề/quy trình duy nhất mà tôi có thể tưởng tượng là có liên quan, vì tôi chưa tạo thêm bất kỳ chủ đề người dùng nào ... Điều lạ lùng là NSLog sửa nó nhưng gọi CFShow (CFStr ("something")) thì không, có nghĩa là nếu đó là một điều kiện chủng tộc, NSLog sẽ chậm hơn rất nhiều so với CFShow. :-) –
ngủ (100) (100 giây) chỉ có thể là một chút quá mức cần thiết. :-) Thay đổi để ngủ cho 100 msec, ở hai nơi mà tôi hình cụ có thể thích một thời gian để bắt kịp với hành động. Tăng gấp đôi nó và thêm một mươi một, nếu bạn thích, độc giả thân yêu trong tương lai. –