EXC_BAD_ACCESS Random crashes on iOS context presentRenderbuffer

I’m getting random crashes at:

if(![context_ presentRenderbuffer:GL_RENDERBUFFER])

File: CCEAGLView-ios.mm

EXC_BAD_ACCESS (code=1, address 0x1)

Cocos2d-x 3.10 (Latest from Git)

Any idea why or how to debug this?

1 Like

OK, I was finally able to identify the cause for it.
The bug is because of the new static __indices in QuadCommand:

void QuadCommand::reIndex(int indicesCount)
{
    if (indicesCount > __indexCapacity)
    {
        CCLOG("cocos2d: QuadCommand: resizing index size from [%d] to [%d]", __indexCapacity, indicesCount);
        __indices = (GLushort*) realloc(__indices, indicesCount * sizeof(__indices[0]));
        __indexCapacity = indicesCount;
    }

When calling realloc, it moves the memory that is being used by OpenGl, thus causing the BAD ACCESS error.
I was able to “Fix” it by calling realloc with null (will work like malloc):

  __indices = (GLushort*) realloc(nullptr, indicesCount * sizeof(__indices[0]));

This solution will cause a leaks, but will prevent the crash from happening. So a better solution is needed.
I hope Cocos2d-x Devs will look at this post and help find a better solution.

2 Likes

thanks! what’s the best way to reproduce it? I want to trigger the crash. thanks.

My game code it too complex to convert to something simple. I also found the error only shows on iOS, i’m using iPad 3.

Maybe an easy way to reproduce it would be to create a code that will cause QuadCommand::reIndex being called more than once on the same frame, so the first command will send the 1st __indices pointer to the renderer, then the second command will call again to reIndex, causing the 1st __indices pointer to be invalid.

I hope I explained myself well :smile:

I’m also calling in my code to:

Director::getInstance()->getRenderer()->render();

For rendering to render texture, so it may be related too.

I’ve also noticed that the crash occurs when an IOS native dialog appears, like a store purchase for example.

If you can give me the exact steps to reproduce it, I’ll try to create a test case. thanks.

1 Like

Hi guys!

I have the same problem with Cocos2d-x 3.11 on iOS 8.4 (iPhone 6). :frowning:
The problem seems to happen randomly during the game!
I never had this problem with Cocos2d-x 3.9!

Making further tests I noticed that the program often crashes after that in the scene enters a particle effect that causes multiple consecutive QuadCommand::reIndex calls.
The output before the crash looks like that:

cocos2d: QuadCommand: resizing index size from [90] to [96]
cocos2d: QuadCommand: resizing index size from [96] to [102]
cocos2d: QuadCommand: resizing index size from [102] to [108]
cocos2d: QuadCommand: resizing index size from [108] to [114]

The following code should fix the problem:

void QuadCommand::reIndex(int indicesCount)
{
    if (indicesCount > __indexCapacity)
    {
        CCLOG("cocos2d: QuadCommand: resizing index size from [%d] to [%d]", __indexCapacity, indicesCount);
        //__indices = (GLushort*) realloc(__indices, indicesCount * sizeof(__indices[0]));
        // TODO - Oren Hack fix for this bug - Will cause some leak but won't crash
        auto tmpindices = __indices;
        __indices = (GLushort*)malloc(indicesCount * sizeof(__indices[0]));

        void** listenerHolder = new void*();

        EventListenerCustom* listener = cocos2d::Director::getInstance()->getEventDispatcher()->addCustomEventListener(cocos2d::Director::EVENT_AFTER_DRAW, [=](cocos2d::EventCustom *event) {

            if (tmpindices)
            {
                free(tmpindices);
            }

            // unregister event listener
            cocos2d::Director::getInstance()->getEventDispatcher()->removeEventListener((EventListener*)*listenerHolder);

            if (listenerHolder)
            {
                delete listenerHolder;
            }

        });

        *listenerHolder = listener;

        __indexCapacity = indicesCount;
    }

    for( int i=0; i < __indexCapacity/6; i++)
    {
        __indices[i*6+0] = (GLushort) (i*4+0);
        __indices[i*6+1] = (GLushort) (i*4+1);
        __indices[i*6+2] = (GLushort) (i*4+2);
        __indices[i*6+3] = (GLushort) (i*4+3);
        __indices[i*6+4] = (GLushort) (i*4+2);
        __indices[i*6+5] = (GLushort) (i*4+1);
    }

    _indexSize = indicesCount;
}
1 Like

Hi Obg1, this seems to work, thanks for sharing! :smile:
I don’t know cocos2d internals, but my guess is that the problem was caused by a free on a buffer still used by ‘someone else’!
Maybe only after the event cocos2d::Director::EVENT_AFTER_DRAW it is safe to free the buffer “__indices”!

Anyway thanks again!

Yes, we can only release that buffer after the frame was drawn. The bug is caused when the memory changes while the frame is being drawn.

Obg1 did you make the bug report on https://github.com/cocos2d/cocos2d-x/issues ?

I think this bug is critical.

Yes, here’s the link for it:

Almost a month ago! :sweat:

Anyway thanks Obg1! :wink:

same here!
I was upgrade 3.10 to 3.11.

Just upgrade to cocos2d-x 3.11 and this bug is appear more frequently in debug mode, i will try in release mode later. Any idea how to fix it?

Edit: Thanks @Obg1, already fixed it :smiley: amazing work :smiley:

Thanks obg1! I can find the fix from your link of github.

I think it is not yet a passed/approved fix, but it just works for me. Thanks Rypac.

@davidchai_6w No probs! I’ve been using the patch over the last few days and have been 100% crash free.

1 Like

Thanks Obg1, you’re a life saver!

I met it on cocos2d-x 3.15 (&3.15.1) and xcode 9 beta. How to fix it?
I tried all the codes above but not fix it. It always happen on launch.