2017-01-15 26 views
0

所以我寫了一些代碼來實現shell(Linux,GCC,C語言),它都可以工作,但是由於某些原因,代碼崩潰時我添加了歷史選項: 它確實沒有(另一個代碼),所以我只會把這裏放在你需要的地方。shell的執行歷史得到分段錯誤

問題是當我在鍵入quit後需要在歷史記錄中保存一箇舊命令,並且當我鍵入退出時,它只是用分段錯誤(核心轉儲)進行壓縮。

歷史記錄保存在鏈接列表,命令字符串和下一個節點的節點的結構中,我也將頭部保存在主體中。關鍵是我只想保存最後15條命令,並且我不關心其他命令,所以每次我想打印列表時,我都會在循環的前15個節點上移動。

當我用GDB調試,我看到的是,代碼崩潰行是行後,他加入了第一個命令的歷史,但當前行真的不相關的歷史:
主:

int main() 
{ 
    history_ll* top; 
    char userInput [CHOICE_LENGTH]; 
    char buff[PATH_MAX]; 
    int flag=1; 
    cmdLine * head; 
    while (flag) 
    { 
     getcwd(buff, PATH_MAX); 
     printf("%s:~$ ",buff); 
     fgets(userInput,MAX_INPUT, stdin); 
     userInput[strlen(userInput)-1]=0; 
     historyAdder(userInput,&top); 
     if(strcmp(userInput,QUIT_OPTION)==0) //segmentation fault here! 
     { 
      flag=0; 
     } 
     else 
     { 
      //doesn't matter 
     } 

    } 
    return 0; 
} 

的historyAdder看起來是這樣的:

void historyAdder(const char *command,history_ll** top) 
{ 
    history_ll* node; 
    strcpy(node->command,command); 
    node->command[strlen(command)]=0; 
    if(historyLength!=0) 
    { 
     node->next= *top; 
    } 
    else 
    { 
     node->next= NULL; 
    } 
    *top = node; 
    historyLength++; 
} 

注:historyLength是一個全局變量

這是結構:

typedef struct history_ll{ 
    char command[CHOICE_LENGTH]; 
    struct history_ll *next; 
}history_ll; 

謝謝幫手!

回答

0

這裏(和在線以下)

void historyAdder(const char *command,history_ll** top) 
{ 
    history_ll* node; 
    strcpy(node->command,command); 
    ... 

代碼取消引用一個未初始化的指針:node否則調用UB和最有可能崩潰該程序。

0

這是可能您的問題:

char userInput [CHOICE_LENGTH]; 
... 
fgets(userInput,MAX_INPUT, stdin); 

除非CHOICE_LENGTH大於或等於MAX_INPUTfgets可以寫過去的userInput陣列,這將導致內存破壞的結束,並導致崩潰。但是,由於您沒有展示我可以爲自己編譯並觀看崩潰的完整程序,所以我不能確定。

兩個條建議給你:

  • 你在Linux上,所以你必須getline。使用它而不是fgets,您不必擔心輸入緩衝區大小。

  • 無論何時您遇到程序崩潰時出現段錯誤,您首先要做的事情應該是valgrind。 valgrind經常會發現,真正的錯誤遠不及您認爲的那樣。

1

這段代碼至少有兩個重要的問題。 之一是,當你從標準輸入讀取緩衝區長度可能甲腎上腺素太短: 定義:

char userInput [CHOICE_LENGTH]; 

但用法是:

fgets(userInput,MAX_INPUT, stdin); 

你應該使用相同的緩衝區大小或斷言MAX_INPUT小於或等於CHOICE_LENGTH

void historyAdder(const char *command,history_ll** top) 
{ 
    history_ll* node; 
    strcpy(node->command,command); /* bad... */ 

其次,您可以通過這裏取消引用未初始化的指針觸發未定義行爲