C - 分段错误将char指针传递给函数

时间:2012-03-29 02:52:16

标签: c arrays pointers segmentation-fault

当我调用一个数组来标记无符号整数集[9]中相应位位的位位置时,我得到一个分段错误,其索引在全局名称数组名[320] [30]中。当我运行程序时,我使用./a.out< data.dat并在列表中加载320个单词的列表。没有超过30个字符。

此外,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);

有人知道为什么我运行程序时会出现分段错误? “Clean”是data.dat列表中的第一个单词。

以下是valgrind的结果

== 1645 ==读取大小4无效

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

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

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

== 1645 ==地址0x9DBED860没有堆叠,malloc'd或(最近)免费

== 1645 ==

== 1645 ==使用信号11(SIGSEGV)的默认操作终止进程

== 1645 == GPF(指针越界?)

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

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

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

3 个答案:

答案 0 :(得分:2)

没有看到整个计划(包括findArrayElement()findElementPos()的定义,很难说清楚。

您可以使用暴力方法并在GDB中运行程序:

gdb ./a.out

从GDB shell中,调用

run < data.dat

当segfault发生时,程序将在调试器中停止。然后你可以打电话

bt

要确切了解程序中发生的段错误。

答案 1 :(得分:2)

看起来你错过了findArrayElement末尾的return语句。这可能就是你的问题。

OP在最后使用findArrayElement更正了return -1

请注意,您还需要检查从findArrayElement返回的-1,否则您可能会对set数组进行索引。

更新: 离开return语句导致OP问题的确切原因是该函数承诺返回一个整数(它的返回类型为int),所以当没有return语句来设置返回值时,将存储返回值的内存/寄存器将包含“垃圾”(当时在内存/寄存器中发生的任何事情)。发生了seg.fault,因为垃圾“返回值”导致索引到数组中以访问不属于应用程序的元素。这种行为是不稳定的,因为它取决于“垃圾”恰好是什么值(它甚至可能是在有效结果范围内的值),因此在某些情况下很难找到。

我知道防止此类错误发生的最佳方法是将编译器的警告级别设置为高,因此它会提供有关缺少返回语句的警告,并且还可能设置编译器将所有警告转换为错误 - 警告通常描述应该解决的问题,以避免可能的不良行为。如果有一个警告,程序员知道这不是一个问题,可以配置编译器(可能通过预处理器语句,虽然这不是一个可移植的方法,因为它是编译器相关的)忽略这些特定的警告。 / p>

答案 2 :(得分:0)

如果你的程序命名为a.out。然后,像这样使用valgrind valgrind --tool=memcheck a.out < data.dat 然后valgrind会在一个特殊的memory中运行你的程序,它会告诉你哪里出错了。不要忘记使用gcc -g将调试信息添加到bin文件中。