簡體   English   中英

訪問由C中的函數修改的字符串數組時出現分段錯誤

[英]Segmentation Fault when accessing string array modified by a function in C

在我的主機中,我定義了一個指向文件名字符串數組(將要確定)的指針:
char **commands = NULL;
然后,我調用一個函數,該argv使用getopt()基於argcargv填充數組。 從函數返回之前,我先打印數組中的文件列表,然后工作正常。

回到我的主文件夾中,我嘗試打印相同的列表(作為確認),但出現了細分錯誤,無法弄清楚該如何解決。 我在下面包含了我的代碼。

有人可以幫我理解為什么我主目錄中的commands無法訪問文件列表的原因。

干杯,
小憩

這是構建文件名列表的函數:

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);
}

您正在傳遞雙指針的副本

char **commands;

進入功能。 當您為它malloc()內存時,它不會更新主函數中的指針,而只會更新雙指針的本地副本。 因此,您嘗試在main中引用NULL指針。 您可以改為將指針傳遞給雙指針(即該函數將使用三指針),然后您的代碼將起作用。

您將需要在函數內部取消引用三指針,如下所示:

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

或者,在函數內部創建一個新的雙指針,進行工作(將代碼大致保留在函數中),然后再返回,將內存分配回從main傳遞的指針中:

*commands = local_commands;

在此功能中:

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

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

您可以通過value接受一個指向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是兩個輸出參數 -也就是說,它們是函數應在其中更改局部變量的參數-因此,您使用&傳遞指向兩者的指針。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM