2011-09-20 2 views
5

Objective-CブロックのスタックにC++クラスのインスタンスをキャプチャしようとすると、私はいくつかの奇妙な動作が見られます。一つは、ローカル変数testがブロックblkで撮影しますと、それは一貫性のある状態を持っていることを期待スタック上の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; 
} 

:次のコードを考えてみましょう。しかし、そうではありません。このコードの出力は次のとおりです。だから、

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に設定せずに削除した場合など、クラッシュする可能性があります。

C++クラスのインスタンス変数はObjective-Cブロックでサポートされていますか? Block Programming Topicsセクションの「C++オブジェクト」は、それらが存在しているように見えますが、明らかにここでは機能していません。これはコンパイラ/ランタイムのバグですか?これはMac OS X v10.6.8上のGCC 4.2.1、Apple build 5666でテストされました。

答えて

6

私はGCCのバグを言っています。

私はGCCでそれをしようとすると、私が手:

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

しかし、LLVM 2.0を使用して:

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

後者はブロックのドキュメントの私の解釈を次の(そしてその唯一のバージョンであります危機的に壊れていない)。

+1

Sweet - あなたは正しい:-)ブロック外で宣言されたstd :: mapの要素にアクセスするとき、BAD_ACCESS例外が発生しました。 [BlockLanguageSpec](http://clang.llvm.org/docs/BlockLanguageSpec.txt)は、 "スタックローカルオブジェクトはコピーコンストラクタを介してブロックにコピーされる"と述べているので、動作するはずです。バグ。 LLVM 3.0に切り替えると問題が解決しました。 – Sebastian

関連する問題