Puede que se deba a un fallo en el propio malloc, como pasaba por ejemplo, en PS2. Pero también puede deberse a una corrupción del montículo de memoria.
Muchas veces, este tipo de fallos, se deben al uso de la caché, sobre todo si un buffer se usa para transferencias DMA o interprocesador y no se ha tenido en cuenta, no solo la alineación del buffer, si no adaptar el tamaño del buffer para que las operaciones de cache no se solapen con otras cosas (por ejemplo, los ARM manejan la cache en bloques de 32 bytes).
Por lo general, cuando asignas un bloque de memoria, se suele añadir unos bytes antes, una estructura que sirve para apuntar al siguiente montículo (ya sea libre u ocupado). Si hay un puntero loco o que se pasa de límite, es probable que corrompas alguna de esas estructuras y se derrumbe todo el sistema de asignaciones, pero también es posible que haya un bug que haga que no se libere bien esa memoria, o que no trabaje bien cuando esta se fragmenta demasiado.
Si no das con el problema, tal vez te venga mejor administrar tu mismo la memoria: haces un malloc con la memoria que vayas a necesitar y tu mismo te ocupas de repartirla como mejor te parezca y cuando tengas que liberarla, no usas el free, si no que vuelves a utilizar la memoria desde el puntero original.
Vamos, algo así como un falso malloc que vaya asignando memoria de forma secuencial (además, ganaras algo de velocidad porque no habrá que ir recorriendo todas las estructuras de asignación buscando memoria libre cada vez que hagas "malloc")