簡體   English   中英

將指向char數組的指針傳遞給函數時發生分段錯誤

[英]Segmentation fault occured on passing a pointer to a char array into a function

這段代碼運行良好,直到我對其進行了修改。

int main(int argc, char** argv)
{
    char command[1024];
    gets(command);
    char *delim = " \t\f";
    char **tokens;
    int i=0;
    /* Extracting tokens from command string */
    for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
    {
       i++;
    }
    return 0;
}

這是由於分段錯誤而崩潰的代碼for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))

代碼

void commandProcess(char command[])
{
    char *delim = " \t\f";
    char **tokens;
    int i=0;
    /* Extracting tokens from command string */
    for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
    {
       i++;
    }
}

int main(int argc, char** argv)
{
    char command[1024];
    gets(command);
    process(command);
    return 0;
}

我知道char command[]會衰減到指針鏈接 ,並且strtok()會修改其第一個參數,在我的情況下,這可能是未定義的行為。 鏈接

因此,有人可以為我提供其他方法,以便我可以使用相同的函數簽名進行工作,並且仍然可以避免該問題嗎?

這似乎是一個小問題,但我無法解決。 :\\我什至嘗試過

void commandProcess(char command1[])
{
    char command[1024];
    int length = strlen(command1);
    strncat(command, command1, length);
    command[length] = '\0';

    char *delim = " \t\f";
    char **tokens;
    int i=0;

    /* Extracting tokens from command string */
    for(tokens[i] = strtok(temp_command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
    {
       i++;
    }

但隨后再次崩潰

for(tokens[i] = strtok(temp_command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))

我認為delimtokens不是罪魁禍首,因為沒有commandProcess()的程序可以很好地處理它們。

您寫入tokens[i] ,但是tokens從未初始化。 取消引用未初始化的指針會調用未定義的行為

這意味着代碼的行為是不可預測的。 它可能會崩潰,可能會顯示奇怪的結果,或者看起來似乎可以正常工作。 同樣,進行看似無關的代碼更改可能會更改未定義行為的顯示方式。 這就是您的情況。

要解決此問題,您需要為tokens分配空間。 在這種情況下,最簡單的方法是制作一個固定大小的指針數組:

char *tokens[1024];

您還可以malloc內存,以便在堆棧上沒有大數組:

char **tokens = malloc(sizeof(char *) * 1024);

由於command的長度為1024,因此令牌的數量不應更大。

正如其他評論和答案所指出的那樣,您需要為收集的令牌指針分配空間。

這是一個固定版本,它也使用fgets()代替過時和危險的gets() 通常,不幸的是, fgets有點麻煩,因為它將后綴\\n留在緩沖區中。 然而,在這里,這很簡單,因為我們可以簡單地在delim變量中添加'\\n'來告訴strtok分割什么。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

#define MAXTOKS 100

void commandProcess(char command[])
{
    char *delim = " \t\f\r\n";
    char *tokens[MAXTOKS+1];
    int i=0;
    /* Extracting tokens from command string */
    for(tokens[i] = strtok(command, delim); tokens[i] != NULL; tokens[i] = strtok(NULL, delim))
    {
       i++;
       if(i > MAXTOKS)
       {
          fprintf(stderr, "too many tokens\n");
          exit(1);   
       }
    }
    for(i = 0; tokens[i] != NULL; i++) printf("%d: \"%s\"\n", i, tokens[i]);
}

int main(int argc, char** argv)
{
    char command[1024];
    fgets(command, sizeof(command), stdin);
    commandProcess(command);
    return 0;
}

暫無
暫無

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

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