5
當我試圖在Objective-C塊的堆棧中捕獲一個C++類的實例時,我看到一些奇怪的行爲。請看下面的代碼:堆棧中的C++類實例是否可以被Objective-C塊捕獲?
#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;
}
人們預計,當局部變量test
得到由塊blk
拍攝的,它有一個一致的狀態。但是,情況並非如此。這段代碼的輸出如下:
0x7fff5fbff650 default constructor
0x7fff5fbff630 copy constructor
about to call blk
0x7fff5fbff5d0 copy constructor
0x7fff5fbff5d0 destructor
flag=1 (test=0x7fff5fbff5d0)
0x7fff5fbff630 destructor
0x7fff5fbff650 destructor
所以當地Test
實例塊看到已呼籲其析構函數!你用它做的任何事情都是未定義的行爲,這很可能導致崩潰(例如,如果析構函數刪除了一個指針而沒有將其設置爲NULL)。
Objective-C塊支持C++類實例變量嗎? Block Programming Topics節「C++對象」似乎表明他們是,但他們顯然不在這裏工作。這是編譯器/運行時的錯誤嗎?這在Mac OS X v10.6.8上的GCC 4.2.1,Apple build 5666上進行了測試。
甜 - 你說得對:-)當訪問塊之外聲明的std :: map的元素時,我遇到了BAD_ACCESS異常。 [BlockLanguageSpec](http://clang.llvm.org/docs/BlockLanguageSpec.txt)指出,「堆棧本地對象通過拷貝常量構造函數複製到塊中」,所以它應該工作,因此是錯誤。切換到LLVM 3.0解決了這個問題。 – Sebastian