Reputation: 223
The following code throws the error:
mem(44582) malloc: * error for object 0x7f9f8a4000e0: pointer being freed was not allocated * set a breakpoint in malloc_error_break to debug Abort trap: 6
I'm not sure what's going on. I'm freeing an area of memory that I explicitly malloc'd, does it have something to do with passing in a pointer to another method?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFERSIZE 10
void readstringbuffered(char *buffer);
int main(int argc, char const *argv[])
{
char *buffer = (char *)malloc(BUFFERSIZE);
readstringbuffered(buffer);
printf("%s",buffer);
free(buffer);
return EXIT_SUCCESS;
}
void readstringbuffered(char *buffer)
{
FILE *source;
source = fopen("hello.txt","r");
int current_size = BUFFERSIZE;
int len = 0;
int c;
while((c = fgetc(source)) != EOF)
{
if(len == current_size-1)
{
current_size *= 2;
char *temp = (char *)realloc(buffer,current_size);
if(!temp)
{
fprintf(stderr,"out of memory");
exit(1);
}
buffer = temp;
}
buffer[len] = c;
len++;
}
buffer[len] = 0;
}
Upvotes: 1
Views: 635
Reputation: 7858
The buffer pointer in main()
will not be modified according to the reallocations you do in readstringbuffered()
, you may write back the buffer pointer using a pointer to the buffer pointer (pBuffer
), like this:
void readstringbuffered(char** pBuffer,size_t* pSize)
{
char* buffer = *pBuffer;
size_t size = MIN_SIZE;
char* newBufferPtr = (char*) realloc(buffer,size);
if(newBufferPtr)
{
buffer = newBufferPtr;
}
else
{
//out of memory
free(buffer);
buffer = NULL;
size = 0;
}
if(buffer)
{
//fill the buffer
}
//must always execute
*pBuffer = buffer;
*pSize = size;
}
int main(int argc, char const *argv[])
{
char* buffer = NULL;
size_t size = 0;
readstringbuffered(&buffer,&size);
if(buffer)
{
printf("%s",buffer);
free(buffer);
}
else
{
//error
}
return EXIT_SUCCESS;
}
Upvotes: 2
Reputation: 19496
realloc() can release the previously allocated memory and allocate it again somewhere else, which makes your buffer pointer in main totally invalid. You can pass buffer by reference and have readstringbuffered() modify it accordingly, or return a pointer to buffer instead of void.
Upvotes: 3
Reputation: 224864
C is a pass by value language. The modifications you make to buffer
inside your readstringbuffered()
function have no effect on the value of buffer
in main()
. If the realloc()
there is ever executed, you've already freed the buffer
that main
knows about, and when you return - BAM - double free.
A possible solution is to pass a pointer to buffer
, rather than buffer
itself. Change the signature of readstringbuffered()
to be:
void readstringbuffered(char **buffer)
And then use *buffer
inside it. At the call site, you'd use readstringbuffered(&buffer)
to pass the necessary pointer.
Upvotes: 8