bullet: fix memory leaks related to Bullet#52
Conversation
|
BTW, I tested this in |
|
Oh, thank you very much! This code was contributed and I was always very suspicious about how the memory is managed there :) Recently I tried to reproduce the leaks in the web version, but the Emscripten fixed-size heap didn't blow up even after a while of "playing", so I put this aside and didn't look further. It's quite bad also because this code was taken as an examples "how to do things" by many students and beginners, suggesting bad practices :/ +1 for using the new Pointer class :)
Since every rigid body is attached to an Object instance, what about creating an Object subclass which would own the rigid body and take care of its removal on destruction? That way you wouldn't need the application destructor at all, I think, and also the objects vector wouldn't be needed.
That... takes a bit of the fun out, since you can't do carpet bombing anymore :) A growing list of shot items would be better, yes. Or, if you do the Object subclass, then this would be also handled implicitly by the SceneGraph parent/child memory management. To avoid unbounded memory growth, I was thinking about iterating through all objects on every cube shoot and throwing away the ones that are too far from the origin. For example iterate on
Could it be possibly the same place as described here? #23 (comment) Interesting if it still didn't get fixed. |
Okay, sounds like a good proposal. Or would it make sense to offer the
Yep, I can definitely understand that ;-) I'll implement a growing list with deletion of far away objects for completeness sake. As you said, people (myself included) look at these examples as the "gold standard" in terms of API usage and best practices. Ideally, the presented solutions should not break when you scale them to real-world problems... |
It would only handle correct detaching from the bullet world at the end, and I think that's not enough to warrant creating a whole new feature for it :) Besides that, there are soft bodies and other things, so for completeness we would need to wrap all of them. Since people need to interact with Bullet anyway (and handle all that manual memory management themselves), I think the less magnum obscures it, the better.
Yup, exactly :) |
|
Carpet bombing restored as ordered. The new approach exposes two new gotchas:
I'd say both points are okay and do not require further changes to the example. Feel free to squash commits on a later merge ;-) |
| GL::defaultFramebuffer.clear(GL::FramebufferClear::Color|GL::FramebufferClear::Depth); | ||
|
|
||
| /* Housekeeping: remove any objects which are far away from the origin */ | ||
| for(Object3D* obj = _scene.children().first(); obj; ) |
There was a problem hiding this comment.
Side-note: Do you have a nicer way of iterating & deleting children than what I did here?
There was a problem hiding this comment.
I thought about while(Object3D* obj = _scene.children().first()), but that would be an infinite loop I'm afraid, since obj = next at the end wouldn't do anything.
😂 👍
This is okay, but I'll put a comment there to make this clearer. Thank you! Will merge this later today / tomorrow, I'm in the middle of doing some unique_ptr -> Pointer cleanup, so it might take a while :) |
|
Merged in c715253 with minor modifications (adapting the style to the surrounding code). Thanks a lot! 👍 |
The Bullet API assumes all allocations by the user must also be freed by the user (source: https://pybullet.org/Bullet/phpBB3/viewtopic.php?t=1660). I think that's a good policy and we should follow it in the Bullet example to show users how to use the API correctly.
I found at least three separate leaks in the example:
The last one is also growing over time, as the user shoots more boxes.
I fixed this by reducing dynamic allocations to a minimum and using
Corrade::Pointerin the other cases. Still, we require some custom deletion code in the destructor, because abtRigidBodyshould be explicitly removed from thebtCollisionWorldbefore it is deleted - if someone has a better idea please tell me ;-)I have to mention that this changes the behavior of the example slightly. If you shoot a new object, the old one is deleted first. If this is undesirable, we should use a growing list of shot items...