The child’s objects are (apparently) randomly set to NULL or an "illegal object"; how to debug this?

I am using Cocos2d-x for a game that I port with Cocos2d-iphone. The original programmer, apparently, used the "function" of Objective-C to not crash when invoking Nile objects as a way to do a lot of messy things.

If this is due to the fact that I do not know, however, in my code I never call release () manually and, of course, do not delete anything like that either. I don’t even call → removeObject () at all (although this will not lead to the same problem as mine).

Now the problem: when the game is running, at random moments (they will not be random, but now they seem obvious), the child nodes get a NULL value. And this not only affects my code, but also Cocos2d internals. Example:

CCLog("----------------"); for(int j = 0; j < this->getChildren()->count(); j++) { CCObject *child = this->getChildren()->objectAtIndex(j); EnemySprite *enemy = dynamic_cast<EnemySprite*>(child); if (enemy != NULL) { CCLog("Enemy with tag %d found", enemy->getTag()); } } EnemySprite *enemy = dynamic_cast<EnemySprite*>(this->getChildByTag(i)); if (enemy == NULL) { CCLog("Now enemy with %d is NULL :(", i); } 

In the getChildren () image, all enemies with tags are there and print this;

  • Enemy with tag 1000 found
  • Enemy with tag 1001
  • Enemy with tag 1002

During the game, it will show it a lot until it shows it;

  • Enemy with tag 1000 found
  • Enemy with tag 1001
  • Enemy with tag 1002
  • Now the enemy with 1001 is NULL :(

and crashes.

In my mind, this should be impossible with the above code, since I just checked, checked and printed this particular object ...

But even more interesting (maybe only for me, maybe this is some kind of stupid mistake), this

  this->getChildByTag(i) 

accidentally mistaken inside; crossing the children, it will find NULL and exit Cocos2d's internal code:

  if(pNode && pNode->m_nTag == aTag) return pNode; 

Then pNode is not NULL (why statements do not run), but it looks like this:

http://o7.no/137JXC4 (screenshot)

The cocos2d :: CCCopying is already a nightmare for me in this project; every time I see this, I know that something is wrong, and I have no idea how to find what it is.

I already added a breakpoint in the line release () delete; it is not called. And I, as I said, does nothing of the sort manually.

I use Xcode / iOS for debugging, but the behavior on Android is the same (but on my computer, Eclipse is slower than Xcode, especially during debugging).

I understand that it would be difficult to give me a solution / reason, however; I would be very happy if someone tells me how to attack this problem. This happens by accident in the entire (rather large) code base, and I don’t understand how to find this problem ...

I hope someone can help!

+4
source share
6 answers

From time to time, dynamic_cast returns 0, even its hard argument is not 0. This happens, for example, when you throw a superclass into a subclass (the so-called "down casting"). Check out this tutorial for more information: http://www.cplusplus.com/doc/tutorial/typecasting/

I can imagine that if the items in your list have a common (unrelated) type super, this could be a problem in your case.

+3
source

As you say, it's hard to say, but here are two ideas.

You can try enabling guard malloc .

Alternatively, you can get something from a static int counter in your suspicious class (e.g. EnonstySprite) deconstructor / constructor to decrement / increment and break / log when it drops below zero.

+1
source

I only see the definition of j , what is i ? I believe that it crashes after CCLog("Now enemy with %d is NULL :(", i); since this line is already registered, it definitely does not crash here.

0
source

CCObjects obeys AutoReleasePool by default, which means Cocos2D-x will control when the object is released. If you use a static constructor for these objects, you can call object-> keep () and object-> release () so that you can manage the memory yourself.

Source: http://www.cocos2d-x.org/projects/cocos2d-x/wiki/Reference_Count_and_AutoReleasePool_in_Cocos2d-x

0
source

If something changes the object of the enemy to NULL, then I will set the breakpoint at the address of the enemy (for 1001). Than,

  • If a breakpoint is hit, it could be memory corruption.
  • If the breakpoint is not pressed and you get NULL, go to getChildByTag() . Then I would replace this->getChildByTag() with dynamic_cast<EnemySprite*>(this->getChildren()->objectAtIndex()) to check if there is any difference.
0
source

In the Build Settings->Other C Flags->Debug and add -o0 and try debugging.

0
source

Source: https://habr.com/ru/post/1479140/


All Articles