栈上的c++类实例可以被Objective-C块捕获吗?

Can C++ class instances on the stack be captured by Objective-C blocks?

本文关键字:Objective-C c++ 实例      更新时间:2023-10-16

当试图在Objective-C块中捕获堆栈上的c++类实例时,我看到了一些奇怪的行为。考虑下面的代码:

#import <Foundation/Foundation.h>
#include <stdio.h>
struct Test
{
  Test() : flag(0) { printf("%p default constructorn", this); }
  Test(const Test& other) : flag(0) { printf("%p copy constructorn", this); }
  ~Test() { flag = 1; printf("%p destructorn", 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 blkn");
  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)。

c++类实例变量被Objective-C块支持吗?块编程主题部分"c++对象"似乎表明它们是,但它们显然在这里不起作用。这是编译器/运行时的错误吗?这是在GCC 4.2.1, Apple build 5666, Mac OS X v10.6.8上测试的。

我认为这是GCC中的一个bug。

当我在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

后者遵循我对块文档的解释(并且是唯一没有明显破坏的版本)。