Tôi thấy một số hành vi lạ khi cố chụp một thể hiện của một lớp C++ trên ngăn xếp trong khối Objective-C. Xét đoạn mã sau:Các cá thể lớp C++ trên ngăn xếp có thể bị chặn bởi các khối Objective-C không?
#import <Foundation/Foundation.h>
#include <stdio.h>
struct Test
{
Test() : flag(0) { printf("%p default constructor\n", this); }
Test(const Test& other) : flag(0) { printf("%p copy constructor\n", this); }
~Test() { flag = 1; printf("%p destructor\n", this); }
int flag;
};
int main(int argc, char **argv)
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Test test;
void (^blk)(void) = ^(void)
{
printf("flag=%d (test=%p)\n", test.flag, &test);
};
printf("about to call blk\n");
blk();
[pool release];
return 0;
}
Một hy vọng rằng khi biến địa phương test
bị bắt giữ bởi khối blk
, nó có một nhà nước thống nhất. Tuy nhiên, đó không phải là trường hợp. Đầu ra của mã này là như sau:
0x7fff5fbff650 default constructor
0x7fff5fbff630 copy constructor
about to call blk
0x7fff5fbff5d0 copy constructor
0x7fff5fbff5d0 destructor
flag=1 (test=0x7fff5fbff5d0)
0x7fff5fbff630 destructor
0x7fff5fbff650 destructor
Ví dụ: địa chỉ Test
mà khối nhìn thấy có hàm hủy của nó! Bất kỳ điều gì bạn làm với nó là hành vi không xác định, rất có thể dẫn đến sự cố (ví dụ: nếu trình hủy đã xóa một con trỏ mà không đặt nó thành NULL).
Biến phiên bản lớp C++ có được hỗ trợ bởi các khối Objective-C không? Phần Block Programming Topics "Đối tượng C++" dường như chỉ ra rằng chúng có, nhưng chúng rõ ràng không hoạt động ở đây. Đây có phải là lỗi trong trình biên dịch/thời gian chạy không? Điều này đã được thử nghiệm trên GCC 4.2.1, Apple xây dựng 5666, trên Mac OS X v10.6.8.
Ngọt - bạn nói đúng :-) Tôi đã chạy vào các trường hợp ngoại lệ BAD_ACCESS khi truy cập vào các phần tử của tiêu chuẩn: bản đồ được khai báo bên ngoài khối. Các [BlockLanguageSpec] (http://clang.llvm.org/docs/BlockLanguageSpec.txt) tiểu bang, rằng "Stack-local đối tượng được sao chép vào một khối thông qua một bản sao const constructor.", Vì vậy, nó sẽ làm việc và do đó là một lỗi. Chuyển sang LLVM 3.0 đã giải quyết được vấn đề. – Sebastian