繁体   English   中英

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

[英]C - Segmentation fault passing char pointer to a function

当我调用一个数组来标记无符号整数集[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)

没有看到整个程序(包括findArrayElement()findElementPos()的定义,很难说。

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

gdb ./a.out

并从GDB shell中调用

run < data.dat

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

bt

要查看程序中segfault的确切位置。

看起来你在findArrayElement的末尾缺少一个return语句。 这可能就是你的问题。

在OP更正了findArrayElement并在结尾return -1之后:

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

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

我知道防止此类错误发生的最佳方法是将编译器的警告级别设置为高,因此它会发出关于缺少return语句的警告,并且还可能将编译器设置为将所有警告转换为错误 - 警告通常描述问题应该解决,以避免可能的不良行为。 如果存在程序员知道不是问题的某个警告,则可以配置编译器(可能通过预处理器语句,尽管这不是可移植的方法,因为它依赖于编译器)来忽略这些特定警告。

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM