Hello,
I am developing an Android application (API version 17, NDK version r8e) with the Cocos2D-x framework, version 2.1rc0-x-2.1.3 and running into segfault issues. The application is nearly complete and works perfectly on iOS. I believe that my installation and setup are working as intended, although I have not found installation instructions that are both comprehensive and up-to-date, so that might be the issue.
The relevant organization works like this: a controller class (call it the Controller
) manages a list of Square
objects, each of which has a pointer to a Shadow
. The Square
and Shadow
objects are subclasses of CCSprite
, and are held in a CCArray
in the Controller
. The Square
s are constructed by the game into a 4x4 grid, and only some Square
s have a Shadow
(if a Square
does not have a Shadow
, the pointer to the Shadow
is set to NULL
). The Controller
populates the Square
s in its constructor, and by logging each Square
’s pointer to its Shadow
, I can see that they are valid after they are created. However, very soon afterward, some of the Squares
suddenly have very strange pointer locations; some of the non-null pointers have turned to addresses such as 0x11
and some of the NULL
pointers have also changed to invalid addresses. What is very strange about this behavior is that it is entirely repeatable: the exact same Square
s have the exact same invalid Shadow
pointer each execution. Moreover, if I remove all of the references to the Shadow
s, the application continues to segfault at the address 0xdeadbaad
, which I believe is a placeholder pointer that indicates an issue in malloc
itself.
Some reference code (I can’t distribute all of the code, unfortunately, but these are the most relevant parts):
Controller
Controller::Controller(CCSize size) {
// some initialization code here...
for (int row = 0; row < kNumRows; row++) {
CCArray* squareRow = CCArray::create();
for (int col = 0; col < kNumCols; col++) {
Square *square = Square::create();
// initialize the square here; i.e. set its position, texture, etc.
if (row == 0) { // only squares in the top row get shadows
// initialize the shadow here
square->setShadow(shadow);
sqaure->setHasShadow(true);
this->addChild(shadow,-1);
}
square->retain();
this->addChild(square);
squareRow->addObject(square);
}
this->squares->addObject(squareRow);
}
this->squares->retain();
// more initialization here...
}
Square
CCSprite* Square::getShadow() {
CCLog("got shadow: %p", this->shadow);
if (!this->hasShadow) {
return NULL;
}
return this->shadow;
}
void Square::setShadow(CCSprite* shadow) {
CCLog("set shadow: %p", shadow);
this->shadow = shadow;
this->shadow->retain();
}
bool Square::getHasShadow() {
return this->hasShadow;
}
void Square::setHasShadow(bool hasShadow) {
this->hasShadow = hasShadow;
}
Square* Square::create() {
Square* s = (Square*)CCSprite::create();
// run some initialization on the square here
s->hasShadow = false;
s->shadow = NULL;
return s;
}
And, finally, a typical stack trace, with some extra debugging information that is not in the code above:
07-16 18:05:30.118: D/cocos2d-x debug info(1332): set shadow: 0x2a14feb0
07-16 18:05:30.118: D/cocos2d-x debug info(1332): set shadow: 0x2a14a9c0
07-16 18:05:30.128: D/cocos2d-x debug info(1332): set shadow: 0x2a14f7e0
07-16 18:05:30.128: D/cocos2d-x debug info(1332): set shadow: 0x2a13b1b0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): square: 0, 0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): got shadow: 0x2a14feb0 // this one is correct
07-16 18:05:30.138: D/cocos2d-x debug info(1332): square: 0, 1
07-16 18:05:30.138: D/cocos2d-x debug info(1332): got shadow: 0x2a14a9c0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): square: 0, 2
07-16 18:05:30.138: D/cocos2d-x debug info(1332): got shadow: 0x11 // should be 0x2a14f7e0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): square: 0, 3
07-16 18:05:30.138: D/cocos2d-x debug info(1332): got shadow: 0x13 // should be 0x2a13b1b0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): square: 2, 0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): got shadow: 0x0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): square: 2, 1
07-16 18:05:30.138: D/cocos2d-x debug info(1332): got shadow: 0x0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): square: 2, 2
07-16 18:05:30.138: D/cocos2d-x debug info(1332): got shadow: 0x0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): square: 2, 3
07-16 18:05:30.138: D/cocos2d-x debug info(1332): got shadow: 0x0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): square: 3, 0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): got shadow: 0x8b // should be 0x0
07-16 18:05:30.138: D/cocos2d-x debug info(1332): square: 3, 1
07-16 18:05:30.138: D/cocos2d-x debug info(1332): got shadow: 0x0
07-16 18:05:30.158: D/cocos2d-x debug info(1332): square: 3, 2
07-16 18:05:30.158: D/cocos2d-x debug info(1332): got shadow: 0x0
07-16 18:05:30.158: D/cocos2d-x debug info(1332): square: 3, 3
07-16 18:05:30.158: D/cocos2d-x debug info(1332): got shadow: 0x0
07-16 18:05:30.158: A/libc(1332): @@@ ABORTING: LIBC: HEAP MEMORY CORRUPTION IN dlmalloc
07-16 18:05:30.158: A/libc(1332): Fatal signal 11 (SIGSEGV) at 0xdeadbaad (code=1), thread 1346 (Thread-78)
You can see that the error was caused by “heap memory corruption”, but the issue that I’m more worried about is that some of the shadow pointers are incorrectly set when they’re being outputted.
Any suggestions would be greatly appreciated! I’ve been attempting to fix this problem for quite some time, and although I’m not extremely experience in C++ and this is my first Cocos2d-x project, I have tried everything that I could think of.
Thanks!