Search code examples
arrayscmultidimensional-arraydynamic-memory-allocationfree

Free 2D Array Of Char Pointers, free(): Invalid Pointers Error


My program runs without error but when I want to free 2D char array (like arguments[0]) it gives me : free(): invalid pointer, fish: Job 1, './a.out' terminated by signal SIGABRT (Abort)

/**
 * @brief Parses the input into arguments
 *
 * EXP:
 * "head -n 5 foo.txt"
 * arguments[0] = "head"
 * arguments[1] = "-n"
 * arguments[2] = "5"
 * arguments[3] = "foo.txt"
 * arguments[4] = NULL
 *
 * @param input
 * @return char**
 */
char** getArguments(char* input, int numOfArgs) {
    char copy_arguments[BUFSIZ]; /* To parse input */
    strcpy(copy_arguments, input);

    char** arguments = calloc(numOfArgs + 1, sizeof(char*));
    if (arguments == NULL) {
        return NULL;
    }

    /*allocate memory for arguments depending their length*/
    char* argument = NULL;
    for (int i = 0; i < numOfArgs; i++) {
        if (i == 0) {
            argument = strtok(copy_arguments, " ");
        } else {
            argument = strtok(NULL, " ");
        }

        int size_of_arg = strlen(argument);
        arguments[i] = calloc((size_of_arg + 1), sizeof(char));
        strcpy(arguments[i], argument);
    }
    arguments[numOfArgs + 1] = NULL;

    return arguments;
}

int main() {
    char **output = getArguments("hello world -n vim", 4);
    free(output[0]);
}

Solution

  • The function invokes undefined behavior. There are allocated numOfArgs + 1 pointers

    char** arguments = calloc(numOfArgs + 1, sizeof(char*));
    

    So the valid range of indices is [0, numOfArgs].

    Thus in this statement

    arguments[numOfArgs + 1] = NULL;
    

    there is an access to memory outside the allocated array.

    Instead you have to write

    arguments[numOfArgs] = NULL;
    

    In general you should check that the returned pointer is not equal to NULL as for example

    if ( output ) free(output[0]);