Christopher Berry
Christopher Berry

Reputation: 675

How to Solve C Program Raises Malloc Error With Opened Files?

I have a program to read a file (given as a parameter in argv) line by line and output it to a different file. Here is the code;

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#define CAT_PREFIX_LEN    4
#define CAT_PREFIX        "bsh_"

int main(int argc, char** argv) {
    FILE *toread, *towrite;
    char *line;
    size_t len = 0;
    ssize_t read;

    char catfile[CAT_PREFIX_LEN + strlen(argv[1]) + 1];

    // Opening file to read
    toread = fopen(argv[1], "r");

    // Create output file name
    strcpy(catfile, CAT_PREFIX);
    strcat(catfile, argv[1]);

    // Opening file to write
    towrite = fopen(catfile, "w");

    while((read = getline(&line, &len, toread)) != -1) {
        fprintf(towrite, line);
    }

    fclose(toread);
    fclose(towrite);
}

However if I try to run this program with a test file test.txt I get the error: convert_script(21115,0x7fffcb3f43c0) malloc: *** error for object 0x10caca4c0: pointer being realloc'd was not allocated *** set a breakpoint in malloc_error_break to debug Abort trap: 6

I've tried multiple things; the first thing I tried was to comment out the whole for loop. If I do comment out the whole for loop, the error goes away. I also tried removing the opening, closing and writing to test.txt. If I remove it, the error also goes away. I don't really know what could be causing it. I am running it on a MacBook Air and compiling it using gcc to compile it.

Upvotes: 0

Views: 280

Answers (1)

Andrew Henle
Andrew Henle

Reputation: 1

char *line;

is not initialized and contains an indeterminate value.

The Linux getline() man page says

If *lineptr is set to NULL and *n is set 0 before the call, then getline() will allocate a buffer for storing the line. This buffer should be freed by the user program even if getline() failed.

Since you're on a Mac, the POSIX getline() standard adds this:

The application shall ensure that *lineptr is a valid argument that could be passed to the free() function. If *n is non-zero, the application shall ensure that *lineptr either points to an object of size at least *n bytes, or is a null pointer.

For strict compliance with the POSIX standard, you should initialize line to NULL:

char *line = NULL;

Edit: The official Apple getline() man page states:

The caller may provide a pointer to a malloced buffer for the line in *linep, and the capacity of that buffer in *linecapp. These functions expand the buffer as needed, as if via realloc(). If linep points to a NULL pointer, a new buffer will be allocated. In either case, *linep and *linecapp will be updated accordingly.

Upvotes: 1

Related Questions