访问由C中的函数修改的字符串数组时的分段错误

时间:2014-03-17 11:17:14

标签: c arrays

在我的主要部分中,我定义了一个指向文件名字符串数组的指针(需要确定):
char **commands = NULL;
然后,我调用一个函数,该函数根据argc& argv使用getopt()。在我从函数返回之前,我打印了数组中的文件列表,它工作正常。

回到我的主要部分,我尝试打印相同的列表(作为确认),但是我得到了一个分段错误,我无法弄清楚如何修复。我在下面提供了我的代码。

有人可以帮我理解为什么我的主要commands无法访问文件列表。

干杯,
N ap个

以下是构建文件名列表的函数:

int getInput (int argc, char **argv, const char *optionList, int *number, int *showEnds, char **commands, int *numberCommands) {

    char c;
    opterr = 0; // Turn off automatic error messages.
    while ( (c = getopt(argc, argv, optionList)) != -1) {
        switch (c) {
            case 'n':
                *number = TRUE;
                break;
            case 'E':
                *showEnds = TRUE;
                break;
            case '?':
                printf("Invalid switch used \"%c\"\n", optopt);
                return EXIT_FAILURE;
                break;
            default:
                printf("Input error occurred");
                return EXIT_FAILURE;
        }
    }
    printf("optind = %d,%d\n",optind, argc);

    commands = malloc(sizeof(char*) * (argc-1));

    if (optind < argc) {
        *numberCommands = (argc - optind);
        int ndx = 1;
        while (optind < argc) {
            int arraySize = (ndx+1)*sizeof(char*);
            commands = realloc (commands,arraySize);
            if (commands == NULL) {
                fprintf(stderr,"Realloc unsuccessful");
                exit(EXIT_FAILURE);
            }
            int stringSize = strlen(argv[optind])+1;
        commands[ndx] = malloc(stringSize);
            if(commands[ndx]==NULL){
                fprintf(stderr,"Malloc unsuccessful");
                exit(EXIT_FAILURE);
            }
            strcpy(commands[ndx],argv[optind]);
            ndx++;
            optind++;
        }
        printf ("Done With Input\n");
        for (int i=1; i<=*numberCommands; i++) {
            printf ("%s\n",commands[i]);
        }
    }
    return EXIT_SUCCESS;
}

这是我的主要内容:

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

    FILE *myInput;
    FILE *myOutput;
    int result;
    const char availOptions[] = "nE";

    // Option flags
    int number = FALSE;     // (Option n) number all output lines
    int showEnds = FALSE;   // (Option E) Show Ends

    char **commands = NULL;
    int numberCommands = 0;

    // Set default to stdin/stdout.
    myInput = stdin;
    myOutput = stdout;
    if (argc > 1) {
        result = getInput(argc,argv, availOptions, &number, &showEnds, commands, &numberCommands);
        if (result != EXIT_SUCCESS) {
            exit(EXIT_FAILURE);
        }
    }
    printf ("Number of files = %d\n", numberCommands);
    for (int i=1; i<=numberCommands; i++) {
        printf ("%s\n",commands[i]);
    }

    echoInput(myInput, myOutput);
}

2 个答案:

答案 0 :(得分:1)

你传递了双指针的副本

char **commands;

进入功能。当你malloc()内存时,它不会更新主函数中的指针,只会更新双指针的本地副本。因此,您尝试在main中使用NULL指针。你可以改为传递一个指向双指针的指针(即函数将采用三指针),那么你的代码就可以了。

您需要取消引用函数内部的三重指针,如下所示:

*commands = malloc(sizeof(char*) * (argc-1));

或者,在你的函数中创建一个新的双指针,完成你的工作(将函数中的代码保持原样)并在返回之前,将内存分配回从main传入的指针:

*commands = local_commands;

答案 1 :(得分:0)

在此功能中:

int getInput (/* ... */, char **commands, int *numberCommands) {

    /* ... */
    commands = malloc(sizeof(char*) * (argc-1));
}

您接受按值指向指针指向char参数。查看呼叫网站,我们可以看到该值始终为(char**)NULL。该参数是函数内的局部变量。即使你改变它,即使调用者碰巧有一个同名的变量,你也永远不会改变调用者的副本。

如果您想更改来电者commands的副本,则需要将该变量的地址传递给您的函数:

int getInput (/* ... */, char ***commands, int *numberCommands) {

    /* ... */
    *commands = malloc(sizeof(char*) * (argc-1));
}

现在,呼叫网站如下所示:

char **commands = NULL;
int numberCommands = 0;
/* ... */
if (argc > 1) {
    result = getInput(/*...*/, &commands, &numberCommands);
    if (result != EXIT_SUCCESS) {
        exit(EXIT_FAILURE);
    }
}

请注意commandsnumberCommands是两个 out-parameters - 也就是说,它们是函数应该更改本地变量的参数 - 所以你'重新使用&将指针传递给它们。