-1

How to avoid double free or corruption (!prev)

I have these structs:

The null device, which always works

static struct mixer null_mixer = {
    .set_device = null_set_device,
    .close_device = null_close_device,
};

List of all available access methods. Uses weak symbols: NULL is not linked in.

static struct mixer *mixers[] = {
    &alsa_mixer,
    &oss_mixer,
    &null_mixer
};

The actual access method.

struct mixer *mixer = &null_mixer;

Sets the mixer device and channel. Try each access method until one succeeds.

void mixer_set_device( const char *devname )
{
    int i;
    mixer->close_device();
    for (i = 0; i < sizeof(mixers)/sizeof(mixers[0]); i++) {
        mixer = mixers[i];
        if (!mixer)
            continue;
        if (mixer->set_device(devname) == 0)
            break;
    }
}

I get the following error when user try to insert wrong value for mixer in gtk entry:

double free or corruption (!prev): 0x0000000002518c00 ***

I think here is problem:

static void alsa_open_mixer( void )
{
    int err;
    static snd_mixer_selem_id_t *sid = NULL;
    if ((err = snd_mixer_open (&handle, 0)) < 0) {
            return;
    }
    if ((err = snd_mixer_attach (handle, card)) < 0) { # memory leak
            goto error;
    }
    if ((err = snd_mixer_selem_register (handle, NULL, NULL)) < 0) {
            goto error;
    }
    if ((err = snd_mixer_load (handle)) < 0) {
            goto error;
    }
    snd_mixer_selem_id_malloc(&sid);
    if (sid == NULL)
            goto error;
    snd_mixer_selem_id_set_name(sid, channel);
    if (!(elem = snd_mixer_find_selem(handle, sid))) {
            goto error;
    }
    if (!snd_mixer_selem_has_playback_volume(elem)) {
            goto error;
    }
    snd_mixer_selem_get_playback_volume_range(elem, &alsa_min, &alsa_max);
    if ((alsa_max - alsa_min) <= 0) {
            goto error;
    }
    snd_mixer_selem_id_free(sid);
    return;

error:
    if (sid)
            snd_mixer_selem_id_free(sid); /* THIS LINE */
    if (handle) {
            snd_mixer_close(handle);
            handle = NULL;
    }
    return;
}

static int alsa_set_device( const char *devname )
{
    int i;

    if (card) free(card);
    card = strdup( devname );
    if( !card ) return -1;

    i = strcspn( card, "/" );
    if( i == strlen( card ) ) {
        channel = "Line";
    } else {
        card[i] = 0;
        channel = card + i + 1;
    }
    alsa_open_mixer();
    if (!handle) {
        return -1;
    }
    return 0;
}

struct mixer alsa_mixer = {
    .set_device = alsa_set_device,
    .close_device = alsa_close_device,
};

double free or corruption (!prev): 0x0000000002518c00 *

UPDATE:

Indicate line with problem

Morten Kristensen
  • 7,412
  • 4
  • 32
  • 52
user1840007
  • 615
  • 1
  • 10
  • 19
  • "wrong value for mixer" means *null_mixer* or soemthing else? – Déjà vu Feb 22 '13 at 13:57
  • this check for oss mixer e.g /dev/mixer:line or alsa mixer e.g. hw:0/Line. If user try to entry hw:1 and card not exist, get this error. Thanks – user1840007 Feb 22 '13 at 14:32
  • 2
    Please tell us in which line this actually happens. Either run it in a debugger, or in valgrind. Make sure you've built with `-g`. – Nikos C. Feb 23 '13 at 06:02
  • Common practice (i guess) avoiding double frees - assigning `NULL` value just after freeing. And always check for already freed parts (NULL) before freeing again. – Kamiccolo Sep 14 '13 at 18:36
  • Possible duplicate of [How to track down a "double free or corruption" error](https://stackoverflow.com/questions/2902064/how-to-track-down-a-double-free-or-corruption-error) – Raedwald Dec 06 '18 at 13:27

1 Answers1

-1

As I can see You work under linux. Then You can use valgrind for finding any memory problems.

Michał Walenciak
  • 4,257
  • 4
  • 33
  • 61