Search code examples
creallocargvargc

realloc(): invalid pointer error when using argc and argv


As part of an exercise, I am developing a small grep-like program in C which is supposed to receive a string and some file names in order to look for that string in the referred files.

I got it working by hardcoding the name of the file and the string:

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

int searchString(char *str1, char *str2) {
    if (strstr(str1, str2) == NULL) {
        return 0;
    } else {
        return 1;
    }
}

void searchInFile(char *filename, char *str) {
    FILE *f;
    int lineno =0;
    size_t len;
    char *buffer;
    f = fopen(filename, "r");
    if (f != NULL) {
        while (getline(&buffer, &len, f) != -1) {
            lineno++;
            if (searchString(buffer, str)) {
                printf("[%s:%d] %s", filename, lineno, buffer);
            } 
        }
    }
    fclose(f);
}

int main() {
    searchInFile("loremipsum.txt", "dolor");
    return 0;
}

But as soon as I modify the code to chage the int main() line to add argc and argv, compile it and then run it, the script returns an error message. The modification is:

int main(int argc, char *argv[]) {
    searchInFile("loremipsum.txt", "dolor");
    return 0;
}

The received error:

* Error in `./a.out': realloc(): invalid pointer: 0x000056424999394d *

Anyone knows why am I getting this error?


Solution

  • Your primary problem with getline() was failing to initialize len = 0; and buffer = NULL; before passing buffer as the lineptr parameter and len as the n parameter. man 3 getline, explains:

    ssize_t getline(char **lineptr, size_t *n, FILE *stream); 
    ...
    If *lineptr is set to NULL and *n is set 0 before the call, then 
    getline() will allocate a buffer for storing the line."
    

    Unless you initialize the pointer for lineptr and value for n, those will contain indeterminate (garbage) values that will prevent getline from automatically handling allocation properly.

    Fixing those issues, providing a couple of minor cleanups, and enabling passing the filename and searchterm as the first and second arguments to your program, you could do something similar to the following:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    /* consider adding parameter for case-insensitive search */
    int searchstring (const char *str1, const char *str2)
    {
        if (strstr (str1, str2) == NULL)
            return 0;
        else
            return 1;
    }
    
    int searchinfile (const char *filename, char *str)
    {
        int lineno = 0;
        size_t len = 0;
        char *buffer = NULL;
        FILE *f = fopen (filename, "r");
    
        if (!f) {   /* validate file open for reading */
            fprintf (stderr, "error: file open failed '%s'.\n", filename);
            return 1;
        }
    
        /* read each line into buffer, search for searchstring */
        while (getline (&buffer, &len, f) != -1) {
            lineno++;
            if (searchstring (buffer, str))
                printf("[%s:%d] %s", filename, lineno, buffer);
        }
        fclose (f);     /* close file */
    
        return 0;
    }
    
    int main (int argc, char **argv) {
    
        if (argc < 3) { /* validate at least 2 arguments given */
            fprintf (stderr, "error: insufficient input.\n"
                    "usage: %s <file> <searchstring>\n", argv[0]);
            return 1;
        }
    
        /* search file argv[1] for string argv[2] */
        if (searchinfile (argv[1], argv[2]))
            fprintf (stderr, "unable to search '%s'.\n", argv[1]);
    
        return 0;
    }
    

    Example Input File

    $ cat dat/captnjack.txt
    This is a tale
    Of Captain Jack Sparrow
    A Pirate So Brave
    On the Seven Seas.
    

    Example Use/Output

    $ /tmp/tmp-david/greplite dat/captnjack.txt Sea
    [dat/captnjack.txt:4] On the Seven Seas.
    

    Note the comment in the code -- it would be a neat trick to pass an additional parameter to indicate whether a case-insensitive search should be performed (and then converting both the line and search-term to lower-case before the search).

    Look things over and let me know if you have further questions.