Closed GoogleCodeExporter closed 9 years ago
Same on Ubuntu Maverick 64 bit.
Original comment by kungfoobar@gmail.com
on 25 Feb 2011 at 2:31
a small patch for a delete on a local var
Original comment by philippe...@gmail.com
on 3 Mar 2011 at 7:15
Attachments:
Thanks for your patch.
But the engine don't delete the game(gkGameLevel) object on finalize step.
If the game object deletion is caused error, m_player or m_pickup deletion can
be problem.
I can't execution test on Linux.
Can you test this code?
gkGameLevel::~gkGameLevel()
{
//comment out delete m_player or pickup, or both.
//delete m_player;
//m_player = 0;
....
//if (m_pickup)
//gkSceneManager::getSingleton().destroy(m_pickup->getResourceHandle());
}
Original comment by harkon...@gmail.com
on 3 Mar 2011 at 3:28
From what I understand: m_player should be deleted, it is not managed by any
resource manager. Destroying the m_pickup scene by hand is not necessary but
should not cause problem. I tested to confirm and indeed the crash still occur.
The problem is that when an object "MomoPhysics" in this case is added to more
than one scene (it is added to the scene it belong by the blender loader than
copied in the level scene). Then at exit, each scene delete its hash table of
objects (gkScene.cpp line 132), and this frees the gkGameObject resource name
string (not the hash or the group name). After the first scene that uses the
object is destroyed, the object has no name anymore. Then when a second scene
containing the object is destroyed it crashes because of a double free (it
tries to free the game object resource name a second time).
Original comment by xavier.thomas.1980@gmail.com
on 11 Mar 2011 at 5:31
The following small patch works around the issue but why does the string does
not get deep copied without this modification? Also the demo still crash later
in the exit procedure because an object want to free a mesh already freed. The
cause is certainly the same and still should be found.
Note that even if this bug only happen in the CppDemo for the moment,
potentially every game can be affected (the issue is in gamekit, not the demo
itself).
I think this is a pretty serious bug.
Index: Engine/gkScene.cpp
===================================================================
--- Engine/gkScene.cpp (revisão 857)
+++ Engine/gkScene.cpp (cópia de trabalho)
@@ -393,9 +393,10 @@
void gkScene::addObject(gkGameObject* gobj)
{
GK_ASSERT(gobj);
-
- const gkHashedString name = gobj->getName();
-
+
+ utString* sn = new utString(gobj->getName());
+ const gkHashedString name = *sn;
+
if (m_objects.find(name) != GK_NPOS)
{
gkPrintf("Scene: Duplicate object '%s' found in this scene\n", name.str().c_str());
Original comment by xavier.thomas.1980@gmail.com
on 12 Mar 2011 at 4:52
Which object owns the resource string?
Original comment by bsd...@gmail.com
on 12 Mar 2011 at 5:55
gobj should own the memory
Original comment by xavier.thomas.1980@gmail.com
on 12 Mar 2011 at 1:10
+ utString* sn = new utString(gobj->getName());
+ const gkHashedString name = *sn;
Is it caused a memory leak?
Original comment by harkon...@gmail.com
on 14 Mar 2011 at 7:30
No it does not cause a memory leak, at the contrary it avoid a double free
crash. I will try to make a test case demonstrating/isolating the issue the
issue.
Here is what I got until so far:
-The crash is because the gkobject resource name is freed twice.
-Using valgrind, I saw the backtrace at the time ot the first free is exactly
the same as at the time of the crash: line 132 of gkScene
m_objects.clear(); line 132
called by gkEngine::finalize()
-Explorating the variables states after the crash showed me that when clearing
the hashtable m_objects, one of the entry key (a gkHashedString) had his char
array memory freed already. The hash was 36145500821
-I set a conditional breakpoint in gkScene::AddObject() with the condition
name.m_hash==36145500821, explorating the memory of the gkObject resource name
and the hashtables entry showed me that the 3 strings (the resource name of
gkobjects and the hashtable entry of the 2 scenes it belongs to) share a
pointer to the same memory containing "MomoPhysics" and was not deep copied.
Original comment by xavier.thomas.1980@gmail.com
on 14 Mar 2011 at 8:14
I think, if the added object is freed twice, we should deep copy the object
itself, not the name member only.
Original comment by harkon...@gmail.com
on 15 Mar 2011 at 3:54
What about using reference counted game objects?
Original comment by bsd...@gmail.com
on 17 Mar 2011 at 1:23
It is not the gameobject that got freed twice, just his name (the char array),
not even his group name or the name hash. I will try to make the most simple
app that I can and reproduce the bug but I don't have much time right now.
Original comment by xavier.thomas.1980@gmail.com
on 17 Mar 2011 at 6:42
My guess with this is that utHashTable in in utTypes.h wich is not aware of
utString.h so when using a string or an hashed string as an entry for a
hashtable the default = operator is used instead of the std::string operator.
Causing the pointer to the string to be copied but not the string itself to be
deep copied.
Also in gkScene::AddObject(), this is where we add the hashtable entry without
deep copying the string, if i try to force a copy using something like:
utString tmpstr;
obj->getName().copy(tmpstr);
I get an error because the type returned by obj->getName() is not the same as
the argument inside copy() but both are supposed to be utString (typedef
std::String utString). Because of the template coding, the error message is
really not that useful.
Another thing to take into consideration is why the crash just happen in
CppDemo. If the string does not get deep copied when added to a scene. Then it
is freed when clearing the scene, then we should have a double free error when
freeing the object (and thus its name for a second time). This with all objects
even when they are part of one scene only.
Original comment by xavier.thomas.1980@gmail.com
on 17 Mar 2011 at 7:00
I noticed the utHashTable::remove function does 2 "unorthodox" calls to the
Entry destructor with this format:
m_bptr[m_size].~Entry();
If I'm not mistaken calling delete [] m_bptr will also call these destructors,
which in turn will call destructors for std::string twice and thus generate the
double free.
I'm not sure why this doesn't happen in the other samples, it might be because
the remove method is never called in those demos?
In any case, commenting the 2 calls to ~Entry() seems to fix the problem (no
segfault).
Valgrind doesn't list any memory leaks in these cases, although I'm not sure
it's working properly and I think it might simply be choking on the application
demanding CPU usage (I get less than 1 FPS when running with valgrind).
Original comment by vek...@gmail.com
on 7 Jan 2012 at 5:19
[deleted comment]
Ok further testing proved to be even more significant. Not only commenting the
2 lines as I mentioned above fixes this issue but it also seems to fix all
other segfaults-on-exit problems reported in the issue list (even one I
reported myself).
For that reason I decided to create a simple patch so that less experienced
people can apply it. You can find it in my report at issue #207 or
alternatively download it directly from here:
http://gamekit.googlecode.com/issues/attachment?aid=2070001000&name=DoubleFree_f
ix.patch&token=Wf5mxmOJCtne0S_q3KUaBV2ErxI%3A1325975458666
Original comment by vek...@gmail.com
on 7 Jan 2012 at 10:36
vekoon, thanks for tracking this out.
All this make sense, but I must admit I never messed much with C++ templates. I
will investigate this further and double check if the patch does not introduce
any memory leaks.
Original comment by xavier.thomas.1980@gmail.com
on 22 Jan 2012 at 2:17
Fixed in r1013
Original comment by xavier.thomas.1980@gmail.com
on 22 Jan 2012 at 4:59
I want to make a keyboard response and create a new Momo ,what should I do?
Original comment by zuo.ri.x...@gmail.com
on 8 Apr 2012 at 12:27
Original issue reported on code.google.com by
philippe...@gmail.com
on 24 Feb 2011 at 8:38