1

我正在努力为声音样本添加随机音高,现在效果很好,但是当我使用完之后尝试释放块时,Mix_FreeChunk() 崩溃了。

我做了一个简化的测试来重现这个问题(SDL 1.2.14 和 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 是使用 Mix_LoadWAV_RW 从文件加载的,s2 是在内存中创建的 s1 的精确副本。后者在释放时崩溃,但前者不会。任何人都知道为什么会发生这种情况?我在这上面花了几个小时,并将其缩小到 SDL_Mixer 中发生的事情,但我无法查看底层源崩溃时发生了什么,现在测试非常简单,它是原始样本,但仍然失败...

具体错误消息的示例:“game.exe 中 0x77c5e3be 的第一次机会异常:0xC0000005:访问冲突读取位置 0x69b0f1d8。”

为什么不能释放内存?

编辑:在进一步检查了隔离测试之后,在 HeapFree(_crtheap, 0, pBlock) 调用期间,s2 的释放在 free.c 中特别崩溃,所以不知何故堆在这几行的空间中被破坏了?Mix_FreeChunk() 中的中间代码实际上非常简单,或多或少只是在缓冲区上调用 free()。既然如此,为什么 s1 会好,但 s2 会失败?

4

1 回答 1

1

似乎问题出在 Windows 上的多个堆上。

Mix_FreeChunk()当我在调试器中分析示例代码时,从 msvcrt.dll 中使用了 SDL_mixer 函数,而从现代 Visual C 运行时库之一(如 msvcr110.dll 或静态版本)free()调用的调用代码。malloc()

如果您要求SDL_malloc()这样做并没有什么不同,因为它确实只是#define SDL_malloc malloc.

我看到的一种解决方案就是强制使用malloc()来自 msvcrt.dll 的:

#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));

该程序对我来说停止了崩溃。

更好的选择可能是自己编译 SDL_mixer 和/或 SDL 库,使用与最终应用程序完全相同的环境设置。

于 2014-04-24T01:45:01.797 回答