简体   繁体   English

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

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

I am getting a segmentation fault when I call an array to mark the bit position of the corresponding bit position in an unsigned int set[9] with its index in the global names array names[320][30]. 当我调用一个数组来标记无符号整数集[9]中相应位位的位位置时,我得到一个分段错误,其索引在全局名称数组名[320] [30]中。 When I run the program, I use ./a.out < data.dat and load a list of 320 words in a list. 当我运行程序时,我使用./a.out <data.dat并在列表中加载320个单词的列表。 None are more than 30 characters. 没有超过30个字符。

Also, typedef unsinged int Set[10]; 另外, typedef unsinged int Set[10];

Here is the code where I call the addName2Set function 这是我调用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);
}

Here is add2Set 这是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);
}

Here is the findArrayElement and findElementPos function 这是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;
}

And finally here is where I call the addName2Member function 最后这里是我调用addName2Member函数的地方

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

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

//addName2Set
addName2Set(set1,key);

Anyone see why there would be a segmentation fault when I run the program? 任何人都知道为什么我运行程序时会出现分段错误? "Clean" is the first word in the data.dat list. “Clean”是data.dat列表中的第一个单词。

Here are the results from valgrind 以下是valgrind的结果

==1645== Invalid read of size 4 == 1645 ==读取大小4无效

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

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

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

==1645== Address 0x9DBED860 is not stack'd, malloc'd or (recently) free'd == 1645 ==地址0x9DBED860没有堆叠,malloc'd或(最近)免费

==1645== == == 1645

==1645== Process terminating with default action of signal 11 (SIGSEGV) == 1645 ==使用信号11(SIGSEGV)的默认操作终止进程

==1645== GPF (Pointer out of bounds?) == 1645 == GPF(指针超出范围?)

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

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

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

Without seeing the whole program (including the definitions of findArrayElement() and findElementPos() it's hard to tell. 没有看到整个程序(包括findArrayElement()findElementPos()的定义,很难说。

You can use a brute force approach and run the program in GDB: 您可以使用强力方法并在GDB中运行该程序:

gdb ./a.out

And from the GDB shell, call 并从GDB shell中调用

run < data.dat

When the segfault happens the program will be stopped in the debugger. 当segfault发生时,程序将在调试器中停止。 You can then call 然后你可以打电话

bt

To see exactly where in your program the segfault happened. 要查看程序中segfault的确切位置。

It looks like you are missing a return statement at the end of findArrayElement . 看起来你在findArrayElement的末尾缺少一个return语句。 This might be your problem right there. 这可能就是你的问题。

After OP corrected findArrayElement with a return -1 at the end: 在OP更正了findArrayElement并在结尾return -1之后:

Note that you will also need a check for that -1 returned from findArrayElement , otherwise you might be underindexing the set array. 请注意,您还需要检查findArrayElement返回的-1,否则您可能会对set数组进行索引。

UPDATE: The exact reason why leaving the return statement off is causing the OP's problem is that the function is promising to return an integer (it's return type is int ), so when there is no return statement to set the return value, the memory/register where the return value would be stored will contain "garbage" (whatever happens to be in memory/register at that time). 更新:关闭return语句导致OP问题的确切原因是函数承诺返回一个整数(它的返回类型是int ),所以当没有return语句来设置返回值时,内存/将存储返回值的寄存器将包含“垃圾”(当时在内存/寄存器中发生的任何事情)。 The seg.fault occured because the garbage "return value" caused indexing into the array to access an element that did not belong to the application. 发生了seg.fault,因为垃圾“返回值”导致索引到数组中以访问不属于应用程序的元素。 This behavior is erratic as it depends on what value the "garbage" happens to be (it might even have been a value that would be within the range of valid results), thus making it hard to find in certain circumstances. 这种行为是不稳定的,因为它取决于“垃圾”恰好是什么值(它甚至可能是在有效结果范围内的值),因此在某些情况下很难找到。

The best way I know of to prevent such errors from happening is to set the compiler's warning level high, so it gives a warning about missing return statements, and possibly also to set the compiler to turn all warnings into errors -- warnings usually describe issues that should be addressed to avoid possible bad behavior. 我知道防止此类错误发生的最佳方法是将编译器的警告级别设置为高,因此它会发出关于缺少return语句的警告,并且还可能将编译器设置为将所有警告转换为错误 - 警告通常描述问题应该解决,以避免可能的不良行为。 If there is a certain warning that the programmer knows is not an issue, the compiler can be configured (possibly through pre-processor statements, although that is not a portable approach, as it is compiler-dependent) to ignore those specific warnings. 如果存在程序员知道不是问题的某个警告,则可以配置编译器(可能通过预处理器语句,尽管这不是可移植的方法,因为它依赖于编译器)来忽略这些特定警告。

if your program named a.out. 如果你的程序命名为a.out。 Then, use valgrind like this valgrind --tool=memcheck a.out < data.dat then valgrind will run your program in a special memory , and it will tell you where is wrong. 然后,使用像valgrind这样的valgrind --tool=memcheck a.out < data.dat然后valgrind会在一个特殊的memory运行你的程序,它会告诉你哪里出错了。 Do NOT forget use gcc -g for add debug info to your bin-file. 不要忘记使用gcc -g将调试信息添加到bin文件中。

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

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