9

Tôi đã gặp phải hành vi lạ objc_setAssociatedObject trong ARC. Xét đoạn mã sau:Các đối tượng liên quan đến mục tiêu-C bị rò rỉ trong ARC

static char ASSOC_KEY; 

@interface DeallocTester : NSObject 
@end 

@implementation DeallocTester 
- (void) dealloc 
{ 
    NSLog(@"DeallocTester deallocated"); 
    //objc_setAssociatedObject(self, &ASSOC_KEY, nil, OBJC_ASSOCIATION_RETAIN); 
} 
@end 

@implementation AppDelegate 
- (void) applicationDidFinishLaunching:(UIApplication *)application 
{ 
    NSObject *test = [[DeallocTester alloc] init]; 
    objc_setAssociatedObject(test, &ASSOC_KEY, [[DeallocTester alloc] init], 
          OBJC_ASSOCIATION_RETAIN); 
} 

tôi là tạo ra một thể hiện của DeallocTester, sau đó tôi đặt DeallocTester khác như một đối tượng liên quan cho nó, sau đó cả hai trong số họ đi ra khỏi phạm vi.

Tôi mong đợi -dealloc của đối tượng đầu tiên được gọi, sau đó đối tượng liên kết sẽ được deallocated quá, nhưng tôi thấy thông báo "DeallocTester deallocated" chỉ in một lần. Nếu tôi bỏ ghi chú dòng objc_setAssociatedObject trong -dealloc, đối tượng thứ hai sẽ được deallocated quá.

Tham chiếu Objective-C nêu rõ rằng các đối tượng liên quan được giải phóng tự động khi hủy đối tượng. Nó là một trình biên dịch/ARC/bất kỳ vấn đề hoặc tôi thiếu một cái gì đó?

Cập nhật

mẫu này đang thực sự làm việc nếu bạn chạy nó từ một dự án hoàn toàn mới. Nhưng tôi có hai dự án hỗ trợ ARC mà nó không có. Tôi sẽ làm một số điều tra và cung cấp một mẫu tốt hơn.

Cập nhật 2

Tôi đã điền một rdar://10636309, Associated objects leaking if NSZombie objects enabled in ARC-enabled project

+0

Nếu bạn đang sử dụng LLVM3 + lý do tại sao bạn đang sử dụng đối tượng liên quan ? Bạn chỉ có thể tạo iVars và thuộc tính trong các danh mục trên lớp. – Abizern

+0

@Abizern Tôi sẽ thêm ngà voi vào 'NSObject', chỉ có thể thêm các thanh màu AFAIR vào một loại mở rộng lớp mà không phải tùy ý. – iHunter

+0

@Abizern Thật sao? Làm thế nào để bạn tạo một ivar trong một thể loại? – jlehr

Trả lời

9

Tôi đã tìm thấy nguồn của sự cố - Tôi đã bật NSZombie đối tượng trong cả hai dự án của tôi khi lỗi này xuất hiện.

Theo như tôi hiểu, khi đối tượng zombie được bật, các trường hợp bình thường được thay thế bằng NSZombie khi deallocation, nhưng tất cả các đối tượng liên quan còn lại! Hãy coi chừng hành vi đó!

Tôi đã tạo một rdar://10636309

Cập nhật: Có một workaround bởi Cédric Luthi, và vấn đề này dường như được cố định trong iOS 6.

+0

Heh, một lý do tốt khác không để mặc định 'NSZombie' được kích hoạt. – jlehr

+0

@jlehr Và các lý do khác là gì? Tôi luôn luôn cho phép họ trong các dự án của tôi, và đã không nhìn thấy bất kỳ hạn chế cho đến nay. Tui bỏ lỡ điều gì vậy? Cảm ơn bạn. – iHunter

+1

Rời khỏi zombie được kích hoạt có thể che dấu một loạt các vấn đề, và tất nhiên nó làm cho ứng dụng của bạn bị rò rỉ tấn bộ nhớ. – jlehr

1

Mã bạn được đăng công trình chính xác như được quảng cáo dưới ARC. Tôi đã viết lại triển khai dealloc của bạn để giúp mọi thứ rõ ràng hơn một chút.

- (void)dealloc 
{ 
    NSLog(@"deallocating %@", self); 
} 

Dưới đây là các bản ghi kết quả:

2012-01-03 06:49:39.754 ARC Stuff[47819:10103] deallocating <DeallocTester: 0x6878800> 
2012-01-03 06:49:39.756 ARC Stuff[47819:10103] deallocating <DeallocTester: 0x688b630> 

Bạn có chắc bạn đang biên soạn với ARC kích hoạt?

+0

Wow! Bạn đang sử dụng phiên bản OS/XCode nào? – iHunter

+0

Tôi đã chạy điều này trong Xcode 4.2 trên 10.7.2. – jlehr

+0

Tôi cũng thế. Bây giờ tôi sẽ kiểm tra lại trong dự án mới. – iHunter

Các vấn đề liên quan