Reputation: 115
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.
Upvotes: 3
Views: 12688
Reputation: 5409
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.
Upvotes: 3
Reputation: 5741
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
Upvotes: 0
Reputation: 4612
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.
Upvotes: 0
Reputation: 12737
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?
Upvotes: 0
Reputation: 115
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.
Upvotes: 1