Malloc and free: memory being freed was not allocated

aiffcfreemallocmemory-management

The following is from the Libaiff library. I get the following error completely randomly (i.e. sometimes my program works flawlessly and sometimes it gets stuck with this error and it always breaks at the same point within this function).
(1949,0x7fff7b82d310) malloc: * error for object 0xd00000000b400: pointer being freed was not allocated
*
set a breakpoint in malloc_error_break to debug

My question is, if r->buffer2 has already been freed, then is it possible for the control to get past the statement if (r->buffer2) and into the block to try and execute free(r->buffer2)? In other words, if r->buffer2 has been freed, shouldn't the if (r->buffer2) prevent the freeing from trying to happen again?

static void AIFF_ReadClose(AIFF_Ref r)
{
    if (r->buffer)
        free(r->buffer);
    if (r->buffer2)
        free(r->buffer2);  // THIS IS WHERE THE BREAK OCCURS EVERYTIME
    Unprepare(r);
    fclose(r->fd);
    free(r);
    return;
}

EDIT:

The following is the definition for AIFF_Ref:

struct s_AIFF_Ref {
    FILE* fd;
    int flags;
    int stat; /* status */
    int segmentSize;
    int bitsPerSample;
    int nMarkers;
    int nChannels;
    double samplingRate;
    uint64_t nSamples;
    int markerPos;
    uint64_t len;
    uint64_t soundLen;
    uint64_t pos;
    uint64_t sampleBytes;
    uint64_t commonOffSet;
    uint64_t soundOffSet;
    uint64_t markerOffSet;
    IFFType format;
    IFFType audioFormat;
    void* decoder;
    void* pdata;
    void* buffer;
    size_t buflen;
    void* buffer2;
    size_t buflen2;
    int tics;
};

typedef struct s_AIFF_Ref* AIFF_Ref;

Can anyone suggest why this strange behavior might be happening and how I might solve it?
Thanks.

Best Answer

From the documentation,

The free function deallocates a memory block (memblock) that was previously allocated by a call to calloc, malloc, or realloc.( Assume first free case )

If memblock is NULL, the pointer is ignored and free immediately returns. (You never came here because, you never set your pointer to NULL)

Attempting to free an invalid pointer (a pointer to a memory block that was not allocated by calloc, malloc, or realloc) may affect subsequent allocation requests and cause errors. ( Assume second free case )

if (r->buffer2) { free(r->buffer2); r->buffer2 = NULL ; // Always set the pointer to NULL, // if you doubt that you may gonna 'free' the memory again,
// somewhere else. }

if (r->buffer2)
{ 
 free(r->buffer2);
 r->buffer2 = NULL ;
}

This is because, when you free the memory, the free assures you that the memory will be free'd but it doesn't assures you that it will delete or NULL'ify the value written in the pointer variable. So, if( r->buffer2 ) holds TRUE for your case and hence, the flow enters the if block.