Search code examples
cpointersreferencedynamic-arrays

Pass dynamic array ponter into func in C ending with "Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)"


I need to change params char array in parser function, but after leaving parser function params array is still NULL and it ends with "Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#define SSH_BIN_PATH "\usr\bin\ssh"

void parser(char *route[4], char **params);

int main(int argc, char *argv[]) {

    char *route[4];
    char **params = NULL;
    parser(route, params);

    for(int i = 0; i < 4; i++) {
        printf("\nRoute: %s\n", params[i]);
    }

    return 0;
}

void parser(char *route[4], char **params) {
    char *userAndPass = NULL;
    char *token = NULL;
    int line_count = 0;
    char lines[100][100];


    FILE *file = fopen("/home/user/Documents/format.txt", "r");
    if (file == NULL) {
        printf("Opening failure.\n");
        exit(EXIT_FAILURE);
    }

    while (fgets(lines[line_count], sizeof(lines[line_count]), file)) {
        size_t length = strlen(lines[line_count]);
        if (lines[line_count][length - 1] == '\n') {
            lines[line_count][length - 1] = '\0';
        }
        line_count++;
    }

    fclose(file);

    if (strcmp(lines[line_count - 1], "exit") != 0) {
        strcpy(lines[line_count], "exit");
        line_count++;
    }

    params = (char**)malloc(line_count * sizeof(char*));
    if (params == NULL) {
        printf("Memory error.\n");
        exit(EXIT_FAILURE);
    }


    for (int i = 0; i < line_count; i++) {
        params[i] = strdup(lines[i]);
        if (params[i] == NULL) {
            printf("Memory error.\n");
            exit(EXIT_FAILURE);
        }
    }

    token = strtok(params[0], "@");
    if (token != NULL) {
        userAndPass = token;

        token = strtok(NULL, ":");
        if (token != NULL) {
            route[2] = token;

            token = strtok(NULL, "@");
            if (token != NULL) {
                route[3] = token;
            }
        }
    }

    token = strdup(userAndPass);
    token = strtok(token, ":");
    if (token != NULL) {
        route[0] = token;
        if (strlen(userAndPass) != strlen(route[0])) {
            token = strtok(NULL, "@");
            if (token != NULL)
                route[1] = token;
        }
        else
            route[1] = "";
    }
}

I can't understand what's a problem, so i even try to do it with 3 pointers like this

void parser(char *route[4], char ***params){
  *params = (char**)malloc(line_count * sizeof(char*));
    if (*params == NULL) {
        printf("Memory error.\n");
        exit(EXIT_FAILURE);
    }


    for (int i = 0; i < line_count; i++) {
        *params[i] = strdup(lines[i]);
        if (*params[i] == NULL) {
            printf("Memory error\n");
            exit(EXIT_FAILURE);
        }
    }
}

int main(){ 
  parser(route, &params);
}

But it didn't help


Solution

  • From the question it seems that you are aware that params must by passed as a pointer. In other words, that you first code example is wrong because it passes params by value.

    You second example is correct with respect to the way params is being passed, i.e. pass a pointer to params instead of passing the value of params.

    However, the second example has another serious problem related to C operator precedence.

    Look at this code:

    *params[i] = strdup(lines[i]);
    

    What is it really doing?

    It is like a) (*params)[i] = strdup(lines[i]);

    or like b) *(params[i]) = strdup(lines[i]);

    That makes a hugh difference....

    The answer is that it is like b) but you actually want it to be a).

    So you need to explicit add the parenthesis and use (*params)[i] = strdup(lines[i]);