1

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.

pat
  • 12,587
  • 1
  • 23
  • 52
Rahul
  • 95
  • 1
  • 2
  • 9
  • Well, the obvious thing is that r->buffer2 doesn't point to an allocated address. Can you paste code that allocates them in the first place? – Phonon Mar 18 '14 at 00:38
  • I've edited my post to include it's definition. – Rahul Mar 18 '14 at 00:39
  • `if (r->buffer2)` does not check if "r->buffer2 has been freed". It checks if it has not been set to 0. Has it? – Dour High Arch Mar 18 '14 at 00:41
  • @Phonon The problem is I'm using this library so I don't fully understand how it goes about doing its thing. The link to the library is: http://aifftools.sourceforge.net/libaiff/ if you'd be willing to download it and take a look. Also, this is shortened version of a longer question I posed if you'd like to take a look: http://stackoverflow.com/questions/22451558/libaiff-closefile-pointer-being-freed-was-not-allocated-occurs-randomly – Rahul Mar 18 '14 at 00:41
  • @DourHighArch I'm not sure unfortunately because this library I'm using does all kinds of things and I'm trying to follow what it does but it's pretty extensive and I'm by now means a C expert. I can scout around the files to see if it has been set to 0 but I don't know if it well help. My previous comment will direct you to some links I posted if you have the time to take a look. – Rahul Mar 18 '14 at 00:44
  • Well: either 1) ->buffer2 was not obtained by malloc() or 2) it was already free()d or 3) it was uninitialised, or 4) you have a memory overwrite somewhere else in your program. NEXT! – wildplasser Mar 18 '14 at 00:44
  • These kind of errors are often caused by heap corruption. Which in turn is almost never caused by the code that fails with the error. Looking in a library that's been around for over a decade for a bug is looking in the wrong corner for the problem. – Hans Passant Mar 18 '14 at 00:45
  • What does `Unprepare(r);` do? does it assume the ->buffer and ->buffer2 elements to be valid ? BTW the conditionals in `if (r->buffer) free(r->buffer);` are not needed: `free(NULL);` is a no-op. – wildplasser Mar 18 '14 at 00:53
  • @Rahul If the library allocates memory for you, it should also free memory for you. There has to be a call to free this memory opaquely. Is there library documentation? – Phonon Mar 18 '14 at 00:53
  • @Phonon The following is the only documentation available: http://aifftools.sourceforge.net/libaiff/MANUAL.html I don't doubt that the library has been set up correctly. It's probably something I'm doing incorrectly but I can't seem to figure out what it is I'm doing wrong. – Rahul Mar 18 '14 at 00:56
  • @wildplasser Thanks for the info. I didn't write this library and since this the library is pretty extensive in size, I don't really know everything it does. My code doesn't even call `Read_Close`. It is called by another function in the library that I call from mine. There are many such layers. – Rahul Mar 18 '14 at 00:59

5 Answers5

2

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.

Abhineet
  • 5,320
  • 1
  • 25
  • 43
1

When you received the error message, one possibility was that it had been freed before, another possibility was that the value of the pointer had been changed to point to another memory.

To avoid this, you must pay attention not to change the pointer before you free it and after having freed memory, you should set the point to NULL.

Metalartis
  • 115
  • 4
0

According to the documentation you liked to, you're already provided with open and close functions, namely

AIFF_Ref AIFF_OpenFile(const char* name, int flags) ;

and

int AIFF_CloseFile(AIFF_Ref r) ;

This call should deallocate memory. Have you tried that?

Phonon
  • 12,549
  • 13
  • 64
  • 114
  • This is what I'm doing. The error occurs at `int AIFF_CloseFile(AIFF_Ref r) ;`. I've presented this issue in significant detail in this earlier question (http://stackoverflow.com/questions/22451558/libaiff-closefile-pointer-being-freed-was-not-allocated-occurs-randomly) if you're willing to take a look. – Rahul Mar 18 '14 at 01:02
0

The short answer to your question is no. Calling free(r->buffer2) does not prevent if (r->buffer2) from evaluating to true and subsequently calling free again. The reason is that free(r->buffer2) does not modify the value of r->buffer2. Think of it this way: if you hired a demolition company to go destroy a building, and you handed them a card with the address of the building you wanted destroyed, would the address written on the card suddenly disappear after they destroyed the building? No. A pointer is no different. It's just an address, stored in a variable that we call a "pointer" because it identifies a memory address. The piece of memory it points to is not the same thing as the pointer itself.

As to what is causing the duplicate call to free(), you haven't provided enough information to ascertain that, so one can only speculate.

Mike Holt
  • 4,452
  • 1
  • 17
  • 24
  • Thanks for your response. My problem is pretty large and I tried presenting it thoroughly here (http://stackoverflow.com/questions/22451558/libaiff-closefile-pointer-being-freed-was-not-allocated-occurs-randomly) but I doubt people will have the time to go through it. – Rahul Mar 18 '14 at 01:06
  • I'm on my way out the door at the moment, but I'll take a look at it later when I get some free time. Hopefully you will have figured it out long before then. Good luck. – Mike Holt Mar 18 '14 at 01:09
0

Please find your question to response and some additional information which might be useful.

if r->buffer2 has been freed, shouldn't the if (r->buffer2) prevent the freeing from trying to happen again?

There is no way to know the information that whether memory has already been freed or not. As someone has pointed out that checking pointer with 'null' does some sanity check and normally we do in that way. But this would work only when is your logic somebody set the pointer with 'null' after freeing the memory, otherwise the 'null' check would not work and your current code would execute the 'free' as the pointer is not assigned to 'null' while freeing the memory.

By looking the address, it looked to me that the 'buffer2' has some garbage value and you should be getting different address value whenever you might be running your program. This might occur in the scenario where 'AIFF_Ref' object might not have been initialized properly and still it holds some garbage value. One way to do it is to set

memset((void*)r, 0, sizeof(struct s_AIFF_Ref));

This would intialize all with default values. This may avoid the chances of any garbage value assigned to yout 'buffer2' variables.

You have mentioned that these are logic of some library hence I would recommend you to use some dynamic tool to understand the error quickly and and at the point where problem is happening.From your description it is also possible that your program has some sort of memory corruption. I think my previous post might be useful for this problem as well. If your program is windows specific, you should see the following link:

https://stackoverflow.com/a/22074401/2724703

If your program is Gnu/Linux specific, you should see the following link:

https://stackoverflow.com/a/22085874/2724703

Community
  • 1
  • 1
Mantosh Kumar
  • 5,659
  • 3
  • 24
  • 48