我写了一段代码来实现哈希函数。将第9个元素“a12a”添加到列表时出现问题,gdb报告如下,似乎问题是在malloc应用内存时发生的。但是在添加第9个元素之前,我在添加第6个元素“ad”时已经成功地通过malloc应用了一次内存,为什么第二次应用内存失败了?
Breakpoint 1, insert (p=0x3d2d10, value=0x4030e8 "a12a") at hashop.c:39
39 id = hash(value);
(gdb) n
40 *current = p + id;
(gdb)
41 if((*current)->value == NULL) {
(gdb)
44 if((lookup(p+id, value)) == NULL) {
(gdb)
45 new = (nList *)malloc(sizeof(nList));
(gdb)
Program received signal SIGSEGV, Segmentation fault.
0x7c938996 in ntdll!RtlDuplicateUnicodeString ()
from C:\WINDOWS\system32\ntdll.dll
(gdb)
我的代码是:
void insert(nList *p, char *value)
{
nList *new, **current;
int id;
id = hash(value);
*current = p + id;
if((*current)->value == NULL) {
(*current)->value = value;
} else {
if((lookup(p+id, value)) == NULL) {
new = (nList *)malloc(sizeof(nList));
new->value = value;
new->next = NULL;
while((*current)->next != NULL) {
(*current) =(*current)->next;
}
(*current)->next = new;
}
}
}
static char *str2[] = {"ac", "ba", "abv", "bc", "bx", "ad", "xx", "aaa", "a12a", "b123"};
每个元素的哈希id如下:
ac, HashId=6
ba, HashId=5
abv, HashId=3
bc, HashId=7
bx, HashId=8
ad, HashId=7
xx, HashId=0
aaa, HashId=1
a12a, HashId=3
b123, HashId=8
从上面的列表中可以确定“bc”和“ad”具有相同的哈希id,因此在我的insert()函数中,我将应用一块内存来存储“ad”。对于“abv”和“a12a”也是如此,我也应用了一块内存,但这次失败了。为什么?任何人都可以搞清楚?理解!
答案 0 :(得分:4)
你用这一行破坏了记忆:
*current = p + id;
将-Wall
传递给gcc以打开所有警告,您会看到:
buggy-hash.c: In function ‘insert’:
buggy-hash.c:19:14: warning: ‘current’ is used uninitialized in this function [-Wuninitialized]
提示:使用gcc -Wall
并在Linux下的Valgrind内存调试器下运行程序会使 lot 更容易找到这些内存问题。
我猜你在Windows下使用CodeBlocks或其他IDE学习C编程?在Visual Studio中以调试模式构建程序也会遇到这些问题。
答案 1 :(得分:0)
问题是我使用p + id作为查找函数的输入,但忘记了p已被* current更改。所以正确的代码是:
void insert(nList *p, char *value)
{
nList *new, **current = &p;
int id;
id = hash(value);
*current += id;
if((*current)->value == NULL) {
(*current)->value = value;
} else {
if((lookup(*current, value)) == NULL) {
new = (nList *)malloc(sizeof(nList));
if(new == NULL)
printf("\nCannot get memory");
else {
new->value = value;
new->next = NULL;
while((*current)->next != NULL) {
(*current) =(*current)->next;
}
(*current)->next = new;
}
}
}
}