C Ошибка сегментации при доступе к индексу массива символов - PullRequest
1 голос
/ 05 декабря 2010

Я программирую цикл обратной связи, который принимает пользовательские команды и обрабатывает аргументы на основе полученной команды.Пока что моя функция выглядит так:

//main loop of the program that keeps repeating, which each cycle taking in one user input
 void mainLoop(){

char input[100]; // initial command
char reg[2]; // registers R1-R7 and PC
char value[20]; // register value
char breakStatus[20]; // can be either "set" or clear"
char breakAddress[80]; // address of break point in hex


//Retrieve user input
printf("Enter a command: ");
scanf("%s", &input);

//Process user input:

//set (completed)
if(strcasecmp(input, "set") == 0){
    scanf("%s", &reg);
    scanf("%s", &value);    
    set(reg, value);
    printf("register value is %s\n", value);
    printf("value[0] is %x\n", value[0]);
    //printf("Setting %s to %s!\n", reg, value);
}

//break (something's wrong here)
else if(strcasecmp(input, "break") == 0){
    scanf("%s", &breakStatus);
    scanf("%s", &breakAddress);

    printf("breakStatus is %s\n", breakStatus);
    printf("breakStatus[0] is %c\n", breakStatus[0]);
    //printf("%sing break point at address %s\n", breakStatus, breakAddress);
    executeBreak(breakStatus, breakAddress);

}


//error (completed)
else
    printf("Error: %s is not a valid command.\n", input);

 }

Моя проблема в том, что всякий раз, когда я пытаюсь получить доступ к breakAddress [index], я получаю Сегментационную ошибку.Когда я пробовал печатать breakStatus и breakAddress, они оба содержали ожидаемые значения (например, входной сигнал был бы break set x0001 , где breakStatus = "set" и breakAddress = "x0001").

Я знаю, что если я использую спецификатор для% c или printf ("breakStatus [0] is% c \ n", breakStatus [0]); , он возвращает действительное значениезначение.Однако я передаю breakStatus и breakAddress в другую функцию, и в этой функции я проверяю, является ли breakAddress [0] == 'x', на что я сразу получаю Сегментацию.

Я не уверен, как справиться с этим.Я попытался привести breakAddress [0] к символу, и я все еще получаю ту же ошибку.

Что меня действительно смущает, так это то, что я в значительной степени закодировал свою часть Set точно таким же образом (та же инициализация char [], тот же процесс scanf), и когда я попытался извлечь индекс из одной из переменных, она отлично работаетхорошо.

Ниже приведены части моих функций set () и executeBreak () для справки:

void set(char* reg, char* val){
    if(val[0] == 'x'){ // no segmentation fault
    sscanf(val+1, "%x", &registers[r]); 
}

void executeBreak(char* stat, char* add){
    if(!(add[0] == 'x')){ // segmentation fault here (tried casting as char also)
    printf("Error: invalid break address");
    return;
    }
}

Если кто-нибудь может подсказать, почему у меня возникает ошибка сегментации в одной функциии ни один из них не был бы высоко оценен.

РЕДАКТИРОВАТЬ: избавился от использования% s в моем выражении printf, так как это не совсем то, где моя проблема.В идеале я хотел бы знать, почему val [0] работает с функцией, а add [0] - нет, так как они получают одинаковые типы аргументов.

Ответы [ 2 ]

4 голосов
/ 05 декабря 2010

Обратите внимание на предупреждения компилятора! :)

Вы определили char breakStatus[20];, то есть массив символов. Затем в выражении printf вы получите printf("...%s...", breakStatus[0]);.

Код форматирования %s ожидает указатель на строку. breakStatus [0], однако, является значением char. Компилятор предупреждает вас о том, что он делает, чтобы это исправить: он превращает значение char в указатель char * (char value = 0 => адрес указателя равен 0). Предположим, что значение char равно нулю, тогда все это волшебным образом превращается в NULL-указатель. Попытка разыменования NULL-указателя (или указателя 0xff, возможно ... значение, по сути, случайное, в конце концов) почти неизбежно вызывает ошибку segfault.

(Обновление: что сказал Влад ... "Вы имели в виду:% c")

2 голосов
/ 05 декабря 2010

Использовать GDB вместо отладочной печати:

#gdb ./myprog
(gdb) r

Когда программа останавливается с SIGSEGV, взгляните на трассировку стека:

(gdb) bt
...