Crash in CCAutoreleasePool

You will crash CCAutoreleasePool if you autorelease anything else int the destructor of something deleted during autorelease:
https://github.com/emablekos/CCAutoreleaseTest

This is due to modification of the array currently being iterated, i believe.

Please let me know if im mistaken, this would be good to fix.

Mark. Thanks a lot for your report and demo!
The internet connection is broken in my home. I am reading the thread on my mobile phone, so cannot reproduce the crash now.
I will check it tomorrow.

Well, the problem is that, you shouldn’t call releasee1~~>autorelease twice in a meesage loop.
The correct usage is
// Releaser.cpp
<pre>
Releaser::Releaser
{
releasee1 = new Releasee; //rc1
releasee2 = new Releasee;
releasee1~~>retain(); //rc2
releasee1~~>autorelease; //rc1
releasee2~~>retain();
releasee2~~>autorelease;
}
Releaser::~Releaser
{
CCLog;
// releasee1~~>autorelease(); //rc0 // error usage, you mustn’t call obj~~>autorelease twice in a same message loop.
releasee1~~>release(); // correct
releasee2->release();
}

Thanks for your response.

Ok, i adjusted it to only call autorelease once, and pushed to github. I was playing around with different scenarios, sorry to confuse the issue.

I still get the crash with a single autorelease on releasee1.

OK, the problem is that, after Releaser::~Release() is called, the Releaser object is destructed. While releasee1->autorelease() will delay the “real release” of releasee1 to the end of this message loop. The time line is:

  • one message loop starts

  • Delayer::onDelay is invoked

    • releaser->autorelease() is invoked
  • before the end of current message loop

  • CCAutoreleasePool::clear() is invoked

    • Delayer::releaser obj is in the autorelease list, and ref = 1, so its destructor is invoked
      • in Releaser::~Releaser(), releasee1->autorelease is invoked, so Releaser::releasee1 obj is added into autorelease list
      • Delayer::releaser obj is deleted
    • CCAutoreleasePool::removeAllObjects() loop the next object, until find Releaser::releasee1
    • but Delayer::release obj is deleted, so the program cannot find releasee1.

In one word, please don’t invoke autorelease in destructor.

Ok, first of all, it is fine, i wont call autorelease in destructor :slight_smile:

BUT, couldnt it be the issue is actually that the array that you are looping over is getting modified while its iterated?

Because you could fix it by copying the array into a temp array and iterating on the temporary array. This would make it a safer API.

I also think this problem exists in CCNotificationCenter.

Or do you know for sure that is always safe with CCArray?