Montao
Montao

Reputation: 255

How can I debug this segmentation fault?

I get a segfault the second time this statement runs:

chunks[i].argv[0] = malloc( strlen(token) * sizeof(char *) + 1 );

The code in context is:

/* TODO: modify str_split to do the copying of its input string if it needs to (e.g. if it uses strtok on it), and return a struct that has the number of "chunks" it split out and the list of chunks. */
struct str_list *list_split(char *a_str, const char a_delim) {
    char **result = 0;
    char **result2 = 0;

    size_t count = 0;
    char *tmp = a_str;
    char *last_comma = 0;

    size_t count2 = 0;
    char *tmp2 = a_str;
    char *last_space = 0;

    char delim[2];
    delim[0] = a_delim;
    delim[1] = 0;
    struct str_list *chunks = NULL;
    /* Count how many elements will be extracted. */
    while (*tmp) {
        if (a_delim == *tmp) {
            count++;
            last_comma = tmp;
        }
        tmp++;
    }

    /* Add space for trailing token. */
    count += last_comma < (a_str + strlen(a_str) - 1);

    /* Add space for terminating null string so caller
       knows where the list of returned strings ends. */
    count++;

    result = malloc(sizeof(char *) * count);
    chunks = malloc(sizeof(chunks));

    //chunks.size = malloc(sizeof(int));
   // counter = (int) count + 1;
    //chunks->size = counter;

    if (result == NULL) {
        printf("Error allocating memory!\n"); //print an error message
        return chunks;; //return with failure
    }

    if (result) {
        size_t idx = 0;
        char *token = strtok(a_str, delim);
        int i = 0;
        while (token) {
            assert(idx < count);
            *(result + idx++) = strdup(token); /* memory leak! how to free() */;
            token = strtok(0, delim);;
        }
        assert(idx == count - 1);
        *(result + idx) = 0;
    }

    chunks->size = (int) count;
    chunks->argv = alloc_argv((unsigned) chunks->size);

    for (int i = 0; i < 2; i++) { //count is wrong
        while (*tmp2) {
            if (' ' == *tmp2) {
                count2++;
                last_space = tmp2;
            }
            tmp2++;
        }

        char* token = strtok(result[i], " ");
        while (token) {
            printf("token: %s\n", token);
            printf("size: %d\n", chunks->size);
            printf("result: %s\n", result[i]);
            printf("i: %d\n", i);
            chunks[i].argv[0] = malloc( strlen(token) * sizeof(char *) + 1 );
            chunks[i].argv[0] = strdup(token);;
            token = strtok(0, " ");
        }

    }

    return chunks;
}

My debugger says nothing interesting. Can you see what is wrong and what should be done? The call to the above function is:

int run_cmd(const char *cmd) {
    struct str_list *chunks = list_split(cmd, '|');
    struct pipeline *pipe = alloc_pipeline(2); //size is the number of pipelines
    for (int i = 0; i < 2; i++) {
        printf("i %d", i);
        for (int j = 0; j < 1; j++) {
            pipe[i].data[j] = chunks[i].argv[j];
        }
    }
    int status = execute_pipeline(pipe);
    // free_pipeline(pipe);
    // free_str_list(chunks);
    return status;
}

The definition of my structs is

struct str_list {
    char *name;
    int size;
    char **argv;

};
struct pipeline {
    char *name;
    int size;
    char **data;
};

Upvotes: 0

Views: 52

Answers (1)

Some programmer dude
Some programmer dude

Reputation: 409432

This line

chunks = malloc(sizeof(chunks));

That allocates the size of the chunks variable, which is a pointer and is usually only 4 or 8 bytes large (depending on if you're on a 32 or 64 bit system).

A str_list structure is larger than that, which means you will write out of bounds of allocated memory, leading to undefined behavior and most likely a crash.

You seem to be using two of this structure, judging by the loops, which means you need to allocate two full str_list structures, which is simplest done by e.g.

chunks = malloc(2 * sizeof *chunks);

Upvotes: 1

Related Questions