views:

406

answers:

5

Apparently this function in SDL_Mixer keeps dying, and I'm not sure why. Does anyone have any ideas? According to visual studio, the crash is caused by Windows triggering a breakpoint somewhere in the realloc() line.

The code in question is from the SVN version of SDL_Mixer specifically, if that makes a difference.

static void add_music_decoder(const char *decoder) 
{ 
  void *ptr = realloc(music_decoders, num_decoders * sizeof (const char **)); 
  if (ptr == NULL) { 
    return; /* oh well, go on without it. */ 
  } 
  music_decoders = (const char **) ptr; 
  music_decoders[num_decoders++] = decoder; 
}

I'm using Visual Studio 2008, and music_decoders and num_decoders are both correct (music_decoders contains one pointer, to the string "WAVE", and music_decoders. ptr is 0x00000000, and the best I can tell, the crash seems to be in the realloc() function. Does anyone have any idea how I could handle this crash problem? I don't mind having to do a bit of refactoring in order to make this work, if it comes down to that.

A: 

Ah, the joys of C programming. A crash in realloc (or malloc or free) can be triggered by writing past the bounds of a memory block -- and this can happen anywhere else in your program. The approach I've used in the past is some flavor of debugging malloc package. Before jumping in with a third party solution, check the docs to see if Visual Studio provides anything along these lines.

jdigital
+2  A: 

Make sure that the SDL_Mixer.DLL file and your program build are using the same C Runtime settings. It's possible that the memory is allocated using one CRT, and realloc'ed using another CRT.

In the project settings, look for C/C++ -> Code Generation. The Runtime Library setting there should be the same for both.

arke
A: 

Crashes are not generally triggered by breakpoints. Are you crashing, breaking due to a breakpoint or crashing during the handling of the breakpoint?

The debug output window should have some information as to why a CRT breakpoint is being hit. For example, it might notice during the memory operations that guard bytes around the original block have been modified (due to a buffer overrun that occurred before add_music_decoder was even invoked). The CRT will check these guard pages when memory is freed and possibly when realloced too.

sean e
Nope, nothing in the output window, and the error popup definitely said it was a windows-triggered breakpoint.
Sukasa
+5  A: 

For one thing, it's not valid to allocate an array of num_decoders pointers, and then write to index num_decoders in that array. Presumably the first time this function was called, it allocated 0 bytes and wrote a pointer to the result. This could have corrupted the memory allocator's structures, resulting in a crash/breakpoint when realloc is called.

Btw, if you report the bug, note that add_chunk_decoder (in mixer.c) is broken in the same way.

I'd replace

void *ptr = realloc(music_decoders, num_decoders * sizeof (const char **));

with

void *ptr = realloc(music_decoders, (num_decoders + 1) * sizeof(*music_decoders));
Steve Jessop
+1  A: 

music_decoders[num_decoders++] = decoder;

You are one off here. If num_decoders is the size of the array then the last index is num_decoders - 1. Therefore you should replace the line with:

music_decoders[num_decoders-1] = decoder;

And you may want to increment num_decoders at the beginning of the function, not at the end since you want to reallow for the new size, not for the old one.

One additional thing: you want to multiply the size with sizeof (const char *), not with double-star.

codymanix
"increment num_decoders at the beginning of the function" - if so, remember to undo it in the failure case.
Steve Jessop