EXC_BAD_ACCESS Random crashes on iOS context presentRenderbuffer

EXC_BAD_ACCESS Random crashes on iOS context presentRenderbuffer
0

#1

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?


Flaws with Renderer, GLProgram and gl state management
#2

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.


#3

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


#4

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.


#5

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


#6

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


#7

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!


#8

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]

#9

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;
}

#10

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!


#11

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.


#12

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

I think this bug is critical.


#13

Yes, here’s the link for it:


#14

Almost a month ago! :sweat:

Anyway thanks Obg1! :wink:


#15

same here!
I was upgrade 3.10 to 3.11.


#16

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:


#17

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.


#18

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


#19

Thanks Obg1, you’re a life saver!


#20

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.