2012-03-29 107 views
1

当我调用数组来标记位于全局名称数组中的索引的无符号整型集[9]中相应位位置的位位置时,出现分段错误名称[320] [30]。当我运行该程序时,我使用./a.out < data.dat并在列表中加载一个320字的列表。没有超过30个字符。C - 分割错误将字符指针传递给函数

此外,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 ==通过0x8048A5D:addName2Set(set.c:145)

== 1645 ==由0x80485D2:主(driver.c:29)

== 1645个==地址0x9DBED860不stack'd ,malloc'd或(近期)fre e'd

== 1645 ==

== 1645 ==过程与信号的默认动作11(SIGSEGV)

== 1645 == GPF终止(指针出界?)

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

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

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

+0

您还需要提供'findArrayElement'和'binarySearch'的定义,或者如果它们不是您的函数,您需要提供哪些库/标题才能使用它们。 seg.fault最可能是由于元素超过了Set(10)的允许大小,但它的值来自上面提到的函数。另外,如果你可以添加变量'set1'的声明,那可能也会有帮助。 – Attila 2012-03-29 03:03:30

+0

我已添加它们。 – manalishi 2012-03-29 03:04:14

+0

它看起来像是在'findArrayElement'结尾缺少return语句。这可能是你的问题。如果不是,请更正问题中的代码。请同时提供'binarySearch'和'names'的定义(用于'addName2Set()' – Attila 2012-03-29 03:12:07

回答

2

看起来您在findArrayElement的末尾缺少返回语句。这可能是你的问题。

OP后修正findArrayElementreturn -1末:

需要注意的是,你还需要检查为-1从findArrayElement回来,否则你可能会underindexing设定的阵列。

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

我知道防止发生这种错误的最好方法是将编译器的警告级别设置得很高,因此它会提示有关缺少返回语句的警告,并且可能还会设置编译器将所有警告转换为错误 - 警告通常会描述应该解决的问题以避免可能的不良行为。如果有某种程序员知道不是问题的警告,可以配置编译器(可能通过预处理器语句,尽管这不是一种便携式方法,因为它依赖于编译器)忽略这些特定的警告。

2

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

您可以使用蛮力的方法和运行GDB的程序:

gdb ./a.out 

而且从GDB外壳,叫

run < data.dat 

当段错误发生时,程序会在被停止调试器。然后,您可以拨打

bt 

要清楚地看到在你的程序的段错误发生。

+0

对不起,我添加了它。 – manalishi 2012-03-29 03:03:51

0

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

+0

我添加了结果。这是一个非常有趣的工具,我以前从未见过或使用过它。感谢看起来非常有用的东西 – manalishi 2012-03-29 03:16:17

+0

不客气,我很高兴你能理解我可怜的英语。:DI认为valgrind的输出已经告诉你,你越界了'set.c:61',你可以使用'gdb'并逐步执行该行,然后查看你的var是否正确,或者只是在该行设置一个断点。 – madper 2012-03-29 03:24:42