Description
I am using:
- Windows 10
- Microsoft Visual Studio 2019 Preview 4.0
- 64-bits build
- Debug build
I build remotery (and the rest of my code) statically with the following defines:
- RMT_USE_OPENGL=1
- RMT_ENABLED=1
There are two scenarios.
SCENARIO 1:
This works fine.
- Main thread initializes Remotery: rmt_CreateGlobalInstance(&rmt);
- Various threads are started that do work using rmt_ScopedCPUSample. One of those threads is a renderer thread, which does rmt_BindOpenGL after activating the context, then uses rmt_ScopedOpenGLSample, and finally when shutting down calls rmt_UnbindOpenGL, and the deactivates the OpenGL context
- When all threads are gone but the main thread, the main thread calls rmt_DestroyGlobalInstance(rmt);
SCENARIO 2:
In this scenario the crash happens.
- Main thread initializes Remotery: rmt_CreateGlobalInstance(&rmt);
- Various threads are started that do work using rmt_ScopedCPUSample. One of those threads is a renderer thread, which does rmt_BindOpenGL after activating the context, then uses rmt_ScopedOpenGLSample, and finally when shutting down calls rmt_UnbindOpenGL, and the deactivates the OpenGL context
- A new set of threads is started, with a new renderer, but reusing the old OpenGL context
- As before in step 2, one of the new threads is the renderer thread, so it makes the OpenGL context current, calls rmt_BindOpenGL, and starts rendering. When shutting down, as before in 2, it calls rmt_UnbindOpenGL and then deactivates the OpenGL context.
- When all threads are gone but the main thread, the main thread calls rmt_DestroyGlobalInstance(rmt);
In this second scenario, the crash happens in the second rmt_UnbindOpenGL call in step 4, which is the second time I'm calling it. The call relevant callstack is short:
!FlattenSampleTree(Sample * sample, unsigned int * nb_samples) Line 4237 C
!FlattenSampleTree(Sample * sample, unsigned int * nb_samples) Line 4242 C
!FreeSampleTree(Sample * sample, ObjectAllocator * allocator) Line 4260 C
!FreePendingSampleTrees(Remotery * rmt, SampleType sample_type, Buffer * flush_samples) Line 5520 C
!_rmt_UnbindOpenGL() Line 6891 C
This is in the following code:
static ObjectLink* FlattenSampleTree(Sample* sample, rmtU32* nb_samples)
{
Sample* child;
ObjectLink* cur_link = &sample->Link;
assert(sample != NULL);
assert(nb_samples != NULL);
*nb_samples += 1;
sample->Link.next = (ObjectLink*)sample->first_child; // CRASH HERE (!!!)
// Link all children together
for (child = sample->first_child; child != NULL; child = child->next_sibling)
{
ObjectLink* last_link = FlattenSampleTree(child, nb_samples);
last_link->next = (ObjectLink*)child->next_sibling;
cur_link = last_link;
}
// Clear child info
sample->first_child = NULL;
sample->last_child = NULL;
sample->nb_children = 0;
return cur_link;
}
The exception thrown is on the line marked "// CRASH HERE (!!!)"
Exception thrown: read access violation. sample was 0xFFFFFFFFFFFFFFD7.
According to the debugger, the Sample* sample variable going in is 0xdddddddddddddddd, indicating the memory was already freed.
It seems somehow rmt_UnbindOpenGL doesn't expect to be called more than once?