FreeEntity crash on AnimMesh?

BlitzMax Forums/MiniB3D Module/FreeEntity crash on AnimMesh?

jhocking(Posted 2010) [#1]
I've just encountered a really frustrating bug that I'm trying to nail down. Basically, when I call FreeEntity on this one specific mesh the program crashes. I've used FreeEntity on a bunch of other objects in the scene with no problem, and the most obvious difference between this object causing the crash and everything so far is that this is the first time I'm calling FreeEntity on an AnimMesh (everything else has been sprites or static meshes.)

It's too early for me to say much for sure and I need to do some troubleshooting to try to isolate the situation, but for now I just wanted to check if anyone had a thought off the top of their head.

ADDITION: oops I forgot to specify I'm using iminib3d


GNS(Posted 2010) [#2]
Just mocked up a quick test to try freeing a bunch of animated meshes. The mesh I used was just a simple Blender default cube that spins around via a single bone. Animate() was called right after the meshes were loaded. I tried freeing them one by one after a certain key was pressed, in large batches or all at once and never had an issue.

Are you doing anything special with the mesh? Referencing it anywhere after it's been freed? Loading animation sequences via LoadAnimSeq()?

Just shooting in the dark here atm.


jhocking(Posted 2010) [#3]
oops I forgot to specify I'm using iminib3d

Thanks for checking. Personally I suspect that the issue is I forgot a reference to the object after freeing it, I'm just wondering if there's anything fundamental that's different about freeing animated meshes and static meshes.



ADDITION: Well I just narrowed down the code to the following snippet-
printf("destroy before");
visual->FreeEntity();
printf("destroy after");


It crashed, and the console output was only "destroy before" so clearly the issue isn't to do with trying to use the object after freeing it. I just realized this is literally the first time I've tried to use FreeEntity on an animated mesh in iminib3d, so I think I'll whip up a minimal example to see if that crashes too.

Can anyone confirm that they have used FreeEntity on animated models in iminib3d, so this isn't simply a bug in iminib3d?


jhocking(Posted 2010) [#4]
okay this definitely looks like a bug in iminib3d, I just tried this code and it crashed:

Mesh* test = Mesh::LoadAnimMesh("dwarf.b3d");
test->FreeEntity();



JoeRetro(Posted 2010) [#5]
Yup, I get the same results using FreeEntity on animated meshes. FreeEntity works fine on static meshes as you stated Joe.

If you put a break point(s) in the FreeEntity func you'll noticed that it tries to free the children meshes which seems to be the culprit.


jhocking(Posted 2010) [#6]
Off the top of my head, I'm guessing the problem has to do with bones being considered child meshes but, well, they aren't meshes.

I guess I'll just hide the models as a temporary workaround to move forward on other things and hope that simon fixes this bug.


jhocking(Posted 2010) [#7]
alright I've been ignoring/working around this problem long enough, I need to actually get this fixed. As the standard first step I turned on the debugger to see where it crashes. It crashes in operator++() of stl_list.h, which is pretty much a one line function for
_M_node = _M_node->_M_next;


That probably means there is somewhere in the iminib3d code that loops through all the linked bones but accidentally attempts to loop beyond the end bones. That's where I'll start looking.


ima747(Posted 2010) [#8]
I think there may be a problem with the lists themselves in iMiniB3D. I get occasional crashes when testing on my phone (as in totally un-repeatable but happens maybe 1/40 compiles... re-run and it's not there...) related to updating entity parents when it loops through an entity's children etc. I was thinking of diving into the list structure and maybe rebuilding it in Objective C just for kicks to see what would happen...

Can you post your mesh somewhere? I'd like to see it crash and poke the relationship if I have time...


jhocking(Posted 2010) [#9]
Sure I can post the mesh, just a minute.

In the meantime, I dug a bit further and went to the part of FreeEntity in entity.mm where it iterates through the child list. I commented out these lines and now it doesn't crash:

//ent->FreeEntity();
//it=child_list.begin();
//it--;

Of course now it isn't freeing the child entities so it's probably generating memory leaks, but hopefully this points someone in the right direction.

EDIT: Here's an animated mesh to load and try to free
http://www.tofrutti.com/dev/gnome.b3d


jhocking(Posted 2010) [#10]
Just a further note about the lines I indicated above...

Commenting out those lines caused a bunch of weird bugs all over my game, which in retrospect I should have expected. I just restored those restored those lines; I need to wait for or eventually figure out a fix for this anyway.

Incidentally, perhaps GNS should post his test mesh as well? If his did work but mine don't, I'm curious what the difference is.


simonh(Posted 2010) [#11]
Looking into this now. A quick fix seems to be to parent the anim mesh to a pivot, and then free the pivot to free the anim mesh without a crash. This is what I do in my game, which is why I haven't encountered the crash before.


simonh(Posted 2010) [#12]
OK, to fix this, you need to comment out the line in Mesh::FreeEntity that deletes the bone (your suspicions about bones being the problem were right Joe).

Also, a related issue is that in entity.h, you need to make the FreeEntity function virtual, like the CopyEntity function. This is the reason that a child anim mesh wasn't crashing when the parent was freed - because only the base class (Entity) FreeEntity was being called for each entity, and not the derived classes (including Mesh) FreeEntity, leading to other potential issues.

There's also an issue with freeing lights. To fix this, you'll need to add:

light_list.remove(this);

After:

Entity::FreeEntity();

In Light::FreeEntity.

However, in order for that to work, you'll need to change light_list from a vector to a list - you just need to replace the 'vector' word with 'list' whenever it appears alongside 'light_list' - and this needs to be done in light.h, at the top of light.mm, and in camera.mm's Camera::Render.

Thanks for your patience while I finally got around to fixing this. I'll release a new version with these fixes soon.


jhocking(Posted 2010) [#13]
Thanks so much! I'll test out your solution tonight to make sure it works.

Incidentally...

you need to comment out the line in Mesh::FreeEntity that deletes the bone


Any chance you can point out which line exactly that is? I'm not looking at the code right now so maybe it's obvious or maybe I'll need a little more direction.

Last edited Tuesday 5th of October 2010 06:31:56 PM GMT


simonh(Posted 2010) [#14]
Yeah it should be obvious. There's a list that goes through all the bones one by one, just need to delete the line that deletes the bone.


jhocking(Posted 2010) [#15]
Thanks again for those fixes, it worked great for several meshes. Some of my animated meshes still cause a crash after using FreeEntity however. The specific line the debugger stopped on is this one in Global::UpdateEntityAnim

if(mesh.anim && mesh.anim_update==true){

I haven't yet dug into the problem to see what's different about these meshes from the ones that freed fine, but the crash on that line makes me suspect iminib3d is still trying to animate the meshes even after they've been freed. I'm thinking that means the FreeEntity method needs to remove them from Entity::animate_list

With that issue though I don't understand why my other meshes which had animations playing didn't crash. I'm guessing there's something really nitpicky happening with the order in which I free meshes and call UpdateWorld.



Any thoughts on what could be causing that crash in Global::UpdateEntityAnim?

Last edited 2010


jhocking(Posted 2010) [#16]
The crash in UpdateEntityAnim pretty much tells you this already, but I isolated the crash to the first time UpdateWorld is called after freeing the meshes. I have this code shortly after freeing the animated meshes:

NSLog(@"before");
Global::UpdateWorld();
NSLog(@"after");


and the console output has "before" but not "after."