| Issue 68: | Internal GC randomly "free" some still used memory block | |
| 1 person starred this issue and may be notified of changes. | Back to list |
Hi, We periodically encounter crashes in our runtime. After some investigation, it seems we access memory freed by the GC (Data breakpoint occurs in BlockData::ClearRecycled()). Difficult to isolate because if we change some code, the bug disappear (probably depending on how blocks are allocated). A partial solution we found is to periodically call GC_Run(), but whow.. :) Is there anyone having same problems ? Maybe we're missing something in the GC usage ? What version of the product are you using? On what operating system? v2.06.0 / msw, 2.06.1 doesn't seems to fix it. Please provide any additional information below. By the way, parsing the code, I found a strange line code. Maye be I didn't figured out its meaning, but I think it's a "typing" or "copy/paste" error. In GCInternal.cpp, method BlockData::Verify(), line 385, there's the following test : if ( !(row_flag * IMMIX_ROW_MARKED) ) Shouldn't be "if ( !(row_flag & IMMIX_ROW_MARKED) )" instead (binary and operator instead of multiply) ? As the issue we have in ClearRecycled() test this flag, we though it could be the pb, but changing it doesn't fix the issue. Thanks, Seb
Dec 21, 2010
Project Member
#1
gameh...@gmail.com
Jan 19, 2011
I'm going to close this issue - if you have a specific example, I may be able to help some more.
Status:
WontFix
Jan 19, 2011
Thanks for your support.
With your help and advices, we found some misusage from our side (maybe to add somewhere in any faq?) :
We added some cpp wrapper function which takes a user callback as a parameter (callback being a haXe function/method), then we stored the "value" passed to cpp wrapped function, and called it later (for async loading purposes for example).
In pseudo-code, the cpp function could look like this
static value s_pCallback;
void MyLoadFunc( some params, value vCallback )
{
s_pCallback = value;
}
My understanding (and which fixed the issue), is that when leaving the MyLoadFunc() context, vCallback is "marked" as not used anymore and then can be freed by the GC. Then if we call the callback later using the stored s_pCallback value, it can be ptotentially freed by the GC !
We found a way to cicrumvent it, in the haXe calling side, by declaring a static (or member if in a class) variable, such as m_pLoadCallback.
Then, to call the MyLoadFunc(), we now proceed like this :
....
m_pLoadCallback = LoadCallBackFunc;
MyLoadFunc( m_pLoadCallback );
....
This way, we ensure the m_pLoadCallback is still referenced and not garbage collected.
I hope my explanations are clear enough, if not don't hesitate to ask me more, but I really think it could be intersting to share with the community.
Thanks again
Seb
Jan 19, 2011
Hi, I fixed this issue in nme (ExternalInterface.cpp) using the "AutoGCRoot", which is designed for exactly this purpose (or you can use the root functions directly). The following code deletes the callback because it is only used once, but you could keep it alive:
AutoGCRoot *sOnCreateCallback = 0;
void OnMainFrameCreated(Frame *inFrame)
{
value frame = inFrame ? ObjectToAbstract(inFrame) : alloc_null();
val_call1( sOnCreateCallback->get(),frame );
delete sOnCreateCallback;
}
value nme_create_main_frame(value *arg, int nargs)
{
if (!sgIDsInit)
InitIDs();
enum { aCallback, aWidth, aHeight, aFlags, aTitle, aIcon, aSIZE };
sOnCreateCallback = new AutoGCRoot(arg[aCallback]);
CreateMainFrame(OnMainFrameCreated,
(int)val_number(arg[aWidth]), (int)val_number(arg[aHeight]),
val_int(arg[aFlags]), val_string(arg[aTitle]), val_string(arg[aIcon]) );
return alloc_null();
}
You are right, this could use some more doco.
Your static member method is also sound.
Jan 19, 2011
Ok thanks, I tried to find a way to duplicate the value callback passed as parameter from cpp side but didn't find anyway, the right api seems to be AutoGCRoot() Thanks for your worl and your precious help ! Seb |