2017-01-15 10 views
0

Итак, я написал некоторый код для реализации оболочки (Linux, GCC, язык C), и все это работает, но по какой-то причине сбой кода при добавлении опции истории: Это действительно doesn 't (другой код), поэтому я поставлю здесь только то, что вам нужно.история в реализации оболочки get segmentation fault

Проблема заключается в том, что я набираю quit после одной старой команды, которая должна быть сохранена в истории, а когда я печатаю 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_INPUT, fgets может написать мимо конца 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... */