I have a method that is being executed on a background thread. From that method I’m trying to dispatch_async a block on the main thread. The block uses a local C++ object which is supposed to be copy constructed according to the Apple reference. I’m getting a segmentation fault and from the trace I see that something very sketchy is going on. Here’s the simplified version of my code.
struct A
{
A() { printf("0x%08x: A::A()\n", this); }
A(A const &that) { printf("0x%08x: A::A(A const &%p)\n", this, &that); }
~A() { printf("0x%08x: A::~A()\n", this); }
void p() const { printf("0x%08x: A::p()\n", this); }
};
- (void)runs_on_a_background_thread
{
A a;
a.p();
dispatch_async(dispatch_get_main_queue(), ^{
printf("block begins\n");
a.p();
printf("block ends\n");
});
}
And this is the output:
0xbfffc2af: A::A()
0xbfffc2af: A::p()
0xbfffc2a8: A::A(A const &0xbfffc2af)
0x057ae6b4: A::A(A const &0xbfffc2a8)
0xbfffc2a8: A::~A()
0xbfffc2af: A::~A()
0xbfffdfcf: A::A(A const &0x57ae6b4)
0xbfffdfcf: A::~A()
block begins
0xbfffdfcf: A::p()
block ends
0x057ae6b4: A::~A()
There are two things that I don’t understand. The first one is why by the time it gets to 0xbfffdfcf: A::p() the destructor on that object has been called already.
The second thing I’m struggling with is why there are so many copy constructors being called. I expect one. That should happen when a copy of a is created to be captured by the block.
I’m using Xcode 3.2.5 with GCC. I experience the same behavior on the simulator and on the device.
I just tested this on LLVM 3.0.
As you can see the destructors get called appropriately in this case, I’d chalk this up to a complier bug in the extremely outdated compiler you’re using.
The copies in this instance seem inline with what I’d expect. The block copies the stack based object into the block when it gets captured. And then again when the block gets copied from the stack to the heap.