سؤال

I was working on adding randomized pitch to sound samples, and that works fine now, but Mix_FreeChunk() crashes when trying to free the chunk after I'm done using it.

I made a simplified test to recreate the issue (SDL 1.2.14 and SDL_mixer 1.2.11):

Mix_Chunk* s1 = rexResourceMgr->getSoundFromFile("data/audio/UI/ALARM.ogg"); // uses Mix_LoadWAV_RW/SDL_RWops to load sample

Mix_Chunk* s2 = (Mix_Chunk*)malloc(sizeof(Mix_Chunk));
s2->allocated = 1;
s2->alen = s1->alen;
s2->abuf = (Uint8*)malloc(s2->alen * sizeof(Uint8));
memcpy(s2->abuf,s1->abuf,s2->alen);
s2->volume = s1->volume;

Mix_FreeChunk(s1); // <-- works fine
Mix_FreeChunk(s2); // <-- crashes somewhere in SDL/SDL_Mixer

s1 is loaded from a file using Mix_LoadWAV_RW, and s2 is an exact copy of s1 created in memory. The latter crashes when freed, but the former doesn't. Anyone have any clues as to why this might be happening? I've spent hours on this and narrowed it down to something happening in SDL_Mixer, but I don't have a way to see what's going on in the underlying source when it crashes, and now the test is so simple it's an exact copy of the original sample, but still fails...

An example of the specific error message: "First-chance exception at 0x77c5e3be in game.exe: 0xC0000005: Access violation reading location 0x69b0f1d8."

Why isn't it able to free the memory?

Edit: After examining the isolated test some more, the freeing of s2 is specifically crashing in free.c during the HeapFree(_crtheap, 0, pBlock) call, so somehow the heap is corrupted in the space of those few lines? The intermediate code in Mix_FreeChunk() is actually quite simple, more or less just calling free() on the buffer. That being the case why would s1 be okay but s2 fail?

هل كانت مفيدة؟

المحلول

It seems that the problem is with multiple heaps on Windows.

When I analyzed the sample code in the debugger, the SDL_mixer function Mix_FreeChunk() used free() from msvcrt.dll, while the calling code called malloc() from one of the modern Visual C Runtime Libraries (like msvcr110.dll or static version).

It doesn't make difference if you call SDL_malloc() for this, because it is indeed just #define SDL_malloc malloc.

The one solution I see is just to force use the malloc() from msvcrt.dll too:

#include <windows.h>

...

typedef void* (*malloc_t)(size_t);
malloc_t msvcrt_malloc = reinterpret_cast<malloc_t>(
    GetProcAddress(GetModuleHandle(TEXT("msvcrt")), "malloc"));

...

Mix_Chunk* s2 = (Mix_Chunk*)msvcrt_malloc(sizeof(Mix_Chunk));
s2->abuf = (Uint8*)msvcrt_malloc(s2->alen * sizeof(Uint8));

The program stopped crashing then for me.

Better option might be to just compile the SDL_mixer and/or SDL libraries yourself, with exactly the same environment settings as your final application.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top