2011-09-20 11 views
5

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.

Trả lời

6

Tôi muốn nói lỗi của nó trong GCC.

Khi tôi thử nó với GCC, tôi nhận được:

0x7fff5fbff5d0 default constructor 
0x7fff5fbff5c0 copy constructor 
about to call blk 
0x7fff5fbff570 copy constructor 
0x7fff5fbff570 destructor 
flag=1 (test=0x7fff5fbff570) 
0x7fff5fbff5c0 destructor 
0x7fff5fbff5d0 destructor 

Nhưng sử dụng LLVM 2.0:

0x7fff5fbff610 default constructor 
0x7fff5fbff600 copy constructor 
about to call blk 
flag=0 (test=0x7fff5fbff600) 
0x7fff5fbff600 destructor 
0x7fff5fbff610 destructor 

Sau đó sau giải thích của tôi về tài liệu hướng dẫn cho các khối (và là phiên bản duy nhất mà không bị hỏng).

+1

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