Cập nhật: Điều này đã được sửa trong SDK iOS 6.1 DP3.Đối tượng được tạo bên trong phạm vi được deallocated ngay cả khi được sử dụng ngoài phạm vi
Tôi đã theo dõi một vụ tai nạn do sử dụng sau khi deal-deal khi xây dựng với ARC bằng cách sử dụng cấu hình bản phát hành mặc định (debug dường như hoạt động tốt). Vấn đề xảy ra khi tạo một đối tượng bên trong một if-scope với một điều kiện không liên tục, gán nó cho một biến từ bên ngoài phạm vi và sau đó chỉ tham chiếu biến bằng mảng Objective-C hoặc literals từ điển.
Đây là trường hợp tái sản xuất nhỏ tôi đã quản lý để tìm thấy:
void test(BOOL arg)
{
id obj = nil;
if (arg) {
obj = [NSObject new];
}
// obj already deallocated here
@[obj];
// but using NSArray works
//[NSArray arrayWithObject:obj];
// @[obj] works if obj is referenced i.e. by NSLog print out
//NSLog(@"%@", obj);
}
int main(int argc, const char * argv[])
{
@autoreleasepool {
test(YES);
}
return 0;
}
Khi tôi xây dựng và chạy này với các đối tượng zombie kích hoạt tôi nhận được thông báo lỗi này:
-[NSObject retain]: message sent to deallocated instance 0x100109100
Như tôi đã nhận xét trong mã nó hoạt động tốt nếu obj
được tham chiếu theo cách khác, như với NSLog
hoặc sử dụng NSArray
thay thế. Tôi đã hiểu sai cách các đối tượng được phát hành với ARC và phạm vi hay đây có phải là lỗi tối ưu trong LLVM hay Clang không?
Tôi đang sử dụng Xcode 4.5.2 với phiên bản tiếng kêu 4.1 (thẻ/Apple/clang-421.11.66) (dựa trên LLVM 3.1svn). Tôi có thể tái tạo nó khi xây dựng cho x86 64 bit cho iOS mô phỏng và Mac OS X và tôi khá chắc chắn cùng một vấn đề xảy ra khi xây dựng cho ARM là vấn đề đầu tiên được tìm thấy khi chạy phát hành xây dựng trên iPhone.
Tôi đã gửi và báo cáo lỗi cho Apple và tạo một open radar report.
Điều gì, nếu có, tôi có bị thiếu không?
Cập nhật, đã làm một số thí nghiệm hơn:
Như Gabro chỉ ra trình biên dịch dịch @[]
một tuyên bố [NSArray arrayWithObjects:count:]
vì vậy tôi đã làm một số xét nghiệm:
// works
id a[] = {obj};
[NSArray arrayWithObjects:a count:1];
// does not work
const id *b = (id[]){obj};
[NSArray arrayWithObjects:b count:1];
// does not work
[NSArray arrayWithObjects:(id[]){obj} count:1];
Vì vậy, tôi đoán được rằng điều này xảy ra khi kết hợp các mảng C và ARC vô danh.
+1 để đăng SSCCE –
theo Apple khi bạn sử dụng mảng theo nghĩa đen, trình biên dịch tạo ra '' 'id objects [] = {obj}; NSUIteger count = sizeof (đối tượng)/sizeof (id); [mảng NSArrayWithObjects: đối tượng đếm: đếm]; '' ' Tôi tự hỏi liệu có một lỗi do đi qua các mảng C chơi –
Rất kỳ quặc. Tôi gọi nó là một lỗi. Tôi đã xem xét việc tháo gỡ '@ [obj]' và 'mảng {NSArray arrayWithObject: obj]' cho x86_64 với tối ưu hóa -Os theo LLVM 4.1; và trình biên dịch chèn một cuộc gọi 'obj_release' vào' obj' trước 'NSArray'. Trừ khi ai đó thông minh hơn tôi chimes, tôi sẽ gọi nó là một lỗi. – FluffulousChimp