Xét đoạn mã sau:nên một khối đen giữ lại tham chiếu khối đống phân bổ
// t included so block1 is a stack block. See [1] below
int t = 1;
SimpleBlock block1 = ^{ NSLog(@"block1, %d", t); };
// copy block1 to the heap
SimpleBlock block1_copied = [block1 copy];
// block2 is allocated on the stack, and refers to
// block1 on the stack and block1_copied on the heap
SimpleBlock block2 = ^{
NSLog(@"block2");
block1_copied();
block1();
};
[block1_copied release];
// When the next line of code is executed, block2_copied is
// allocated at the same memory address on on the heap as
// block1_copied, indicating that block1_copied has been
// deallocated. Why didn't block2 retain block1_copied?
SimpleBlock block2_copied = [block2 copy];
block2_copied();
[block2_copied release];
đâu, cho đầy đủ, SimpleBlock được xác định bởi:
typedef void (^SimpleBlock)(void);
Như đã nêu bởi những nhận xét trong mã , các thử nghiệm của tôi (sử dụng cả GCC 4.2 và LLVM 2.0) cho thấy block1_copied được deallocated bởi thời gian [block2 copy] được gọi, nhưng theo tài liệu mà tôi đã đọc [1,3], các khối là các đối tượng và khối mục tiêu-c giữ lại các đối tượng mục tiêu-c mà chúng tham chiếu [2] (trong biến phi cá thể c ase). Ngoài ra, lưu ý rằng khi block2 được sao chép, tham chiếu của nó tới block1 cũng được thay đổi thành tham chiếu đến một bản sao mới của block1 (khác với block1_copied), như mong đợi, vì khối sao chép bất kỳ khối nào mà chúng tham chiếu [ 2].
Vì vậy, những gì đang xảy ra ở đây?
A) Nếu khối giữ lại đối tượng mục tiêu-c mà chúng tham chiếu và chặn là đối tượng mục tiêu-c, tại sao block1_copied deallocated trước khối 2 vượt quá phạm vi?
B) Nếu chặn khối sao chép mà chúng tham chiếu và nếu gửi - (id) bản sao vào khối được phân bổ theo heap thực sự chỉ tăng số lần giữ lại, tại sao block1_copied deallocated trước block2 vượt quá phạm vi?
C) Nếu đây là hành vi mong đợi, tài liệu giải thích ở đâu?
[1] http://cocoawithlove.com/2009/10/how-blocks-are-implemented-and.html
[2] http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html
[3] http://clang.llvm.org/docs/BlockLanguageSpec.txt
Footnote: Trong các thử nghiệm của tôi, kết quả của chạy mã này là một cuộc gọi vô hạn đệ quy để block2_copied(), vì block1_copied() có cùng địa chỉ bộ nhớ như block2_copied.
+1 thú vị .... –