C - Ошибка сегментации, передающая символьный указатель на функцию - PullRequest
1 голос
/ 29 марта 2012

Я получаю ошибку сегментации, когда я вызываю массив, чтобы отметить битовую позицию соответствующей битовой позиции в множестве без знака int [9] с его индексом в именах массива глобальных имен [320] [30].Когда я запускаю программу, я использую ./a.out Кроме того, typedef unsinged int Set[10];

Вот код, где я вызываю функцию addName2Set

//add name to unsigned int set
void addName2Set(Set set, char *key){
    int index;

    //binary search to get index for key
    index = binarySearch(names, key, 0, 319);
    //call add2set to add index to set
    add2Set(set, index);
}

Вот add2Set

//add value passed to set passed
void add2Set(Set set, int index){
  int element, position;

  //find which element, set[element] of set index is in
  element = findArrayElement(index);

  //convert index to bit position 0-31 in set[element]
  position = findElementPos(element, index);

  //in set[element], set bit position 'position' to 1
  set[element] = set[element] | (1 << position);
}

Вот функции findArrayElement и findElementPos

//for unsigned int set[i], return i
int findArrayElement(int index){
  //index range [j,i]
  int i;
  int j=0;
  //element in set array
  int element;

  //loop through [j,i], return element if range true
  for(i=31; i<320; i+=32){
    if(i <= i && index >= j){       
      return element;
    }
    j+=32;
    element++;
  }
}

//find bit position 0-31 corresponding to index
int findElementPos(int element, int index){
    int j;
    int position;

    j = element*32;
    position = index - j + 1;

    //return bit position
    return position;
}

И, наконец, вот где я вызываю функцию addName2Member

//declare key pointer
char *key = (char*)malloc(30);

//set search word to pointer key
strcpy(key, "clean");

//addName2Set
addName2Set(set1,key);

Кто-нибудь увидит причину ошибки сегментации, когдаЯ запускаю программу?«Очистить» - это первое слово в списке data.dat.

Вот результаты valgrind

== 1645 == Недопустимое чтение размера 4

==1645 == в 0x8048860: add2Set (set.c: 61)

== 1645 == по 0x8048A5D: addName2Set (set.c: 145)

== 1645 == по 0x80485D2:main (driver.c: 29)

== 1645 == Адрес 0x9DBED860 не является стековым, malloc или (недавно) свободным

== 1645 ==

== 1645 == Процесс завершается с действием по умолчанию для сигнала 11 (SIGSEGV)

== 1645 == GPF (указатель вне границ?)

== 1645 ==в 0x8048860: add2Set (set.c: 61)

== 1645 == по 0x8048A5D: addName2Set (set.c: 145)

== 1645 == по 0x80485D2: main (драйвер).c: 29)

Ответы [ 3 ]

2 голосов
/ 29 марта 2012

Похоже, вы пропустили оператор возврата в конце findArrayElement.Это может быть вашей проблемой прямо сейчас.

После того, как OP исправил findArrayElement с return -1 в конце:

Обратите внимание, что вам также понадобится проверка для этого -1, возвращенного из findArrayElement, в противном случае вы можете переиндексировать установленный массив.

ОБНОВЛЕНИЕ: Точная причина, по которой отключение оператора return вызывает проблему OP, состоит в том, что функция обещает вернуть целое число (тип возвращаемого значения int), поэтому, когда нет оператора возврата для установки возвращаемого значения, память / регистр, в котором будет храниться возвращаемое значение, будет содержать «мусор» (что бы ни случилось в памяти / регистре в это время).Произошел seg.fault, потому что «возвращаемое значение» мусора привело к индексации в массиве для доступа к элементу, который не принадлежал приложению.Такое поведение является ошибочным, поскольку оно зависит от того, какое значение имеет «мусор» (это могло даже быть значение, которое находится в диапазоне допустимых результатов), что затрудняет его поиск в определенных обстоятельствах.

Лучший из известных мне способов предотвращения подобных ошибок - установить высокий уровень предупреждения компилятора, чтобы он предупреждал о пропущенных операторах возврата, и, возможно, также настроить компилятор на превращение всех предупреждений в ошибки - обычно предупрежденияопишите проблемы, которые следует устранить, чтобы избежать возможного плохого поведения.Если есть определенное предупреждение, что программист знает, что это не проблема, компилятор может быть настроен (возможно, с помощью инструкций препроцессора, хотя это не переносимый подход, поскольку он зависит от компилятора), чтобы игнорировать эти конкретные предупреждения.

2 голосов
/ 29 марта 2012

Не видя всей программы (включая определения findArrayElement() и findElementPos(), трудно сказать.

Вы можете использовать метод грубой силы и запустить программу в GDB:

gdb ./a.out

А из оболочки GDB вызовите

run < data.dat

Когда произойдет ошибка, программа будет остановлена ​​в отладчике. Затем можно позвонить

bt

, чтобы точно узнать, гдев вашей программе произошел сбой.

0 голосов
/ 29 марта 2012

если ваша программа называется a.out. Затем используйте valgrind , как это valgrind --tool=memcheck a.out < data.dat тогда valgrind запустит вашу программу в специальном memory и сообщит вам, в чем дело. НЕ забывайте использовать gcc -g для добавления отладочной информации в ваш bin-файл.

...