nope
nope

Reputation: 223

Freeing a non-allocated pointer

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

Answers (3)

Sam
Sam

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

itsme86
itsme86

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

Carl Norum
Carl Norum

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

Related Questions