C - strcmp 分段错误?
我似乎在 strcmp 函数的某个地方遇到了分段错误。 我对 C 还很陌生,我不明白为什么它会给我这个错误。
int linear_probe(htable h, char *item, int k){
int p;
int step = 1;
do {
p = (k + step++) % h->capacity;
}while(h->keys[p] != NULL && strcmp(h->keys[p], item) != 0);
return p;
}
gdb:
Program received signal SIGSEGV, Segmentation fault.
0x0000003a8e331856 in __strcmp_ssse3 () from /lib64/libc.so.6
(gdb) frame 1
#1 0x0000000000400ea6 in linear_probe (h=0x603010, item=0x7fffffffde00 "ksjojf", k=-1122175319) at htable.c:52
编辑:插入代码和htable结构
int htable_insert(htable h, char *item){
unsigned int k = htable_word_to_int(item);
int p = k % h->capacity;
if(NULL == h->keys[p]){
h->keys[p] = (char *)malloc(strlen(item)+1);
strcpy(h->keys[p], item);
h->freqs[p] = 1;
h->num_keys++;
return 1;
}
if(strcmp(h->keys[p], item) == 0){
return ++h->freqs[p];
}
if(h->num_keys == h->capacity){
return 0;
}
if(h->method == LINEAR_P) p = linear_probe(h, item, k);
else p = double_hash(h, item, k);
if(NULL == h->keys[p]){
h->keys[p] = (char *)malloc(strlen(item)+1);
strcpy(h->keys[p], item);
h->freqs[p] = 1;
h->num_keys++;
return 1;
}else if(strcmp(h->keys[p], item) == 0){
return ++h->freqs[p];
}
return 0;
}
struct htablerec{
int num_keys;
int capacity;
int *stats;
char **keys;
int *freqs;
hashing_t method;
};
谢谢
编辑:valgrind - 我输入随机值以添加到表中
sdkgj
fgijdfh
dfkgjgg
jdf
kdjfg
==25643== Conditional jump or move depends on uninitialised value(s)
==25643== at 0x40107E: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643==
fdkjb
kjdfg
kdfg
nfdg
lkdfg
oijfd
kjsf
vmf
kjdf
kjsfg
fjgd
fgkjfg
==25643== Invalid read of size 8
==25643== at 0x400E0E: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== Address 0x4c342a0 is not stack'd, malloc'd or (recently) free'd
==25643==
==25643== Invalid read of size 8
==25643== at 0x400E2B: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== Address 0x4c342a0 is not stack'd, malloc'd or (recently) free'd
==25643==
==25643== Invalid read of size 1
==25643== at 0x4A06C51: strcmp (mc_replace_strmem.c:426)
==25643== by 0x400E3C: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== Address 0x210 is not stack'd, malloc'd or (recently) free'd
==25643==
==25643==
==25643== Process terminating with default action of signal 11 (SIGSEGV)
==25643== Access not within mapped region at address 0x210
==25643== at 0x4A06C51: strcmp (mc_replace_strmem.c:426)
==25643== by 0x400E3C: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== If you believe this happened as a result of a stack
==25643== overflow in your program's main thread (unlikely but
==25643== possible), you can try to increase the size of the
==25643== main thread stack using the --main-stacksize= flag.
==25643== The main thread stack size used in this run was 8388608.
==25643==
==25643== HEAP SUMMARY:
==25643== in use at exit: 1,982 bytes in 28 blocks
==25643== total heap usage: 28 allocs, 0 frees, 1,982 bytes allocated
==25643==
==25643== LEAK SUMMARY:
==25643== definitely lost: 0 bytes in 0 blocks
==25643== indirectly lost: 0 bytes in 0 blocks
==25643== possibly lost: 0 bytes in 0 blocks
==25643== still reachable: 1,982 bytes in 28 blocks
==25643== suppressed: 0 bytes in 0 blocks
==25643== Rerun with --leak-check=full to see details of leaked memory
==25643==
==25643== For counts of detected and suppressed errors, rerun with: -v
==25643== Use --track-origins=yes to see where uninitialised values come from
==25643== ERROR SUMMARY: 7 errors from 4 contexts (suppressed: 6 from 6)
Segmentation fault (core dumped)
static unsigned int htable_word_to_int(char *word){
unsigned int result = 0;
while(*word != '\0'){
result = (*word++ + 31 * result);
}
return result;
}
I appear to be getting a segmentation fault somewhere with the strcmp function.
I'm still very new to C and I can't see why it gives me the error.
int linear_probe(htable h, char *item, int k){
int p;
int step = 1;
do {
p = (k + step++) % h->capacity;
}while(h->keys[p] != NULL && strcmp(h->keys[p], item) != 0);
return p;
}
gdb:
Program received signal SIGSEGV, Segmentation fault.
0x0000003a8e331856 in __strcmp_ssse3 () from /lib64/libc.so.6
(gdb) frame 1
#1 0x0000000000400ea6 in linear_probe (h=0x603010, item=0x7fffffffde00 "ksjojf", k=-1122175319) at htable.c:52
Edit: insertion code and htable struct
int htable_insert(htable h, char *item){
unsigned int k = htable_word_to_int(item);
int p = k % h->capacity;
if(NULL == h->keys[p]){
h->keys[p] = (char *)malloc(strlen(item)+1);
strcpy(h->keys[p], item);
h->freqs[p] = 1;
h->num_keys++;
return 1;
}
if(strcmp(h->keys[p], item) == 0){
return ++h->freqs[p];
}
if(h->num_keys == h->capacity){
return 0;
}
if(h->method == LINEAR_P) p = linear_probe(h, item, k);
else p = double_hash(h, item, k);
if(NULL == h->keys[p]){
h->keys[p] = (char *)malloc(strlen(item)+1);
strcpy(h->keys[p], item);
h->freqs[p] = 1;
h->num_keys++;
return 1;
}else if(strcmp(h->keys[p], item) == 0){
return ++h->freqs[p];
}
return 0;
}
struct htablerec{
int num_keys;
int capacity;
int *stats;
char **keys;
int *freqs;
hashing_t method;
};
Thanks
Edit: valgrind - me entering random values to add to table
sdkgj
fgijdfh
dfkgjgg
jdf
kdjfg
==25643== Conditional jump or move depends on uninitialised value(s)
==25643== at 0x40107E: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643==
fdkjb
kjdfg
kdfg
nfdg
lkdfg
oijfd
kjsf
vmf
kjdf
kjsfg
fjgd
fgkjfg
==25643== Invalid read of size 8
==25643== at 0x400E0E: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== Address 0x4c342a0 is not stack'd, malloc'd or (recently) free'd
==25643==
==25643== Invalid read of size 8
==25643== at 0x400E2B: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== Address 0x4c342a0 is not stack'd, malloc'd or (recently) free'd
==25643==
==25643== Invalid read of size 1
==25643== at 0x4A06C51: strcmp (mc_replace_strmem.c:426)
==25643== by 0x400E3C: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== Address 0x210 is not stack'd, malloc'd or (recently) free'd
==25643==
==25643==
==25643== Process terminating with default action of signal 11 (SIGSEGV)
==25643== Access not within mapped region at address 0x210
==25643== at 0x4A06C51: strcmp (mc_replace_strmem.c:426)
==25643== by 0x400E3C: linear_probe (htable.c:51)
==25643== by 0x401095: htable_insert (htable.c:87)
==25643== by 0x400AB7: main (main.c:75)
==25643== If you believe this happened as a result of a stack
==25643== overflow in your program's main thread (unlikely but
==25643== possible), you can try to increase the size of the
==25643== main thread stack using the --main-stacksize= flag.
==25643== The main thread stack size used in this run was 8388608.
==25643==
==25643== HEAP SUMMARY:
==25643== in use at exit: 1,982 bytes in 28 blocks
==25643== total heap usage: 28 allocs, 0 frees, 1,982 bytes allocated
==25643==
==25643== LEAK SUMMARY:
==25643== definitely lost: 0 bytes in 0 blocks
==25643== indirectly lost: 0 bytes in 0 blocks
==25643== possibly lost: 0 bytes in 0 blocks
==25643== still reachable: 1,982 bytes in 28 blocks
==25643== suppressed: 0 bytes in 0 blocks
==25643== Rerun with --leak-check=full to see details of leaked memory
==25643==
==25643== For counts of detected and suppressed errors, rerun with: -v
==25643== Use --track-origins=yes to see where uninitialised values come from
==25643== ERROR SUMMARY: 7 errors from 4 contexts (suppressed: 6 from 6)
Segmentation fault (core dumped)
static unsigned int htable_word_to_int(char *word){
unsigned int result = 0;
while(*word != '\0'){
result = (*word++ + 31 * result);
}
return result;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
除了
htable
中的值可能是无效指针(即既不是 NULL 也不是指向合适的 C 字符串的指针)的可能性之外,您还遇到一个严重问题如果它既不包含 NULL 也不包含您要查找的字符串,则为无限循环。对于眼前的问题,请尝试将代码更改为:
这些调试语句应该告诉您出了什么问题。
由于您得到:
就在崩溃之前,很明显有人正在为
k
传递一个虚假值。负数的模运算是 C 标准中定义的实现,因此pos
也会得到负值。由于h->pos[-30]
将是未定义的行为,所以所有的赌注都失败了。找到并修复传入该虚假值(可能是未初始化的变量)的代码,或者通过在函数开头将:
更改为:
来保护您的函数。我实际上会同时做这两件事,但我非常偏执:-)
并且,基于另一个更新(哈希键计算,如果您生成一个
unsigned int
并且然后盲目地将其用作有符号的 int ,您很有可能获得负值:此输出:
我的建议是对明确意味着无符号的值使用无符号整数。
Apart from the possibility that the values in your
htable
may be invalid pointers (i.e., neither NULL nor a pointer to a decent C string), you have a serious problem of encountering an infinite loop if it contains neither a NULL nor the string you're looking for.For the immediate problem, try changing the code to:
Those debug statements should give you an indication as to what's going wrong.
Since you're getting:
right before the crash, it's evident that someone is passing in a bogus value for
k
. The modulo operation on negative numbers is implementation defined in the C standard so you're getting a negative value forpos
as well. And sinceh->pos[-30]
is going to be undefined behaviour, all bets are off.Either find and fix the code that's passing in that bogus value (probably an uninitialised variable) or protect your function by changing:
into:
at the start of your function. I'd actually do both but then I'm pretty paranoid :-)
And, based on yet another update (the hash key calculation, if you generate an
unsigned int
and then blindly use that as a signedint
, you've got a good chance of getting negative values:This outputs:
My suggestion is to use unsigned integers for values that are clearly meant to be unsigned.
如果您使用的是 Linux,请尝试 valgrind。它可以告诉您有关无效访问、内存泄漏、未初始化变量等的信息。输出可能看起来很混乱且难以阅读,但如果您继续尝试,它会给您带来奖励。发生了什么事:
-g
开关构建程序以包含调试信息valgrind ./myprogram
正如我所说,输出可能看起来很混乱,所以也许首先尝试一些简单的程序(普通的空主程序),看看一切正常时它是什么样子,然后尝试故意让你的程序崩溃,比如:
并查看输出。
可以在此处找到带有示例的很好的基本介绍。
当您提供 valgrind 输出时,我将开始修复那里列出的问题。首先,
条件跳转或移动取决于未初始化的值
错误。您可以按照 valgrind 建议使用--track-origins=yes
重新运行 valgrind 以查看更多详细信息,然后修复它(代码片段中没有行号,我无法为您提供更多帮助)。那么
Invalid read of size 1
错误意味着您已经在访问不属于您的内存,但仅读取它,因此它“不介意”。但这仍然是一个不应该发生的错误,因此请修复它(如果第一个错误修复没有修复)。最后,
访问不在映射区域内
是对未分配的内存的写入。现在尝试按照 valgrind 建议(例如使用开关重新运行它)修复错误(以便 valgrind 列出它们)。
If you are on linux, try valgrind. It can tell you about invalid accesses, memory leaks, uninitialized variables, etc. The output may seem messy and hard to read, but if you keep trying, it will reward you. What is going on:
-g
switch to include debugging informationvalgrind ./myprogram
As I said, the output may seem very messy, so maybe first try some simple program (plain empty main) to see how it looks like when everything is ok, then try to deliberately crash your program, like:
and see the output.
A nice basic introduction with examples can be found here.
As you provided valgrind output, I would start to fix problems listed there. First the
Conditional jump or move depends on uninitialised value(s)
error. You can rerun valgrind with--track-origins=yes
as valgrind suggests to see more details, then fix it (you don't have line numbers in the code snippets, I cannot help you more).Then the
Invalid read of size 1
error means you are already accessing memory which is not yours, but reading it only, so it "doesn't mind". But it is still an error which should not happen, so fix it (if not fixed by the first error fix).And finally, the
Access not within mapped region
is a write to memory which is not allocated.Now try fixing the errors (in order valgrind lists them) following valgrind suggestions (like reruning it with switches).
好吧,您没有包含围绕填充此哈希表等的 htable 的代码。
strcmp 可能出现段错误,因为您要么给它一个 NULL 字符串,要么给它一个未正确以 0 结尾的字符数组...
well you did not include the code around htable around filling this hash table etc.
strcmp probably segfaulted because you either gave it a NULL string or an array of chars not properly ending with a 0....
h->keys 是否完全用 NULL 初始化?否则里面会有随机指针。
顺便说一句,
如果函数发出错误信号,请务必检查函数返回的有效性,无论错误情况有多么不可能。
malloc()
失败时返回 NULL。Is h->keys completely initialized with NULLs? Else you have random pointers inside.
BTW,
Always check the return of a function for validity if it signals an error, no matter how unlikely the error case may be.
malloc()
returns NULL on failure.乍一看,我的猜测是您的段错误来自
p
- 您从未初始化该变量,因此不能保证它从零开始;据您所知,它可能从-123456
开始,然后您将访问无效的内存地址。编辑:误读了 do-while 循环。忽略这一段。再看一眼,我会检查
h->keys[p]
是否是一个以 null 结尾的字符串 -strcmp
继续读取值,直到达到零字节;如果没有这样的字节,它可以继续下去,直到遇到无效的内存地址。At first glance, my guess is that your segfault comes from
p
- you're never initializing that variable, so it is not guaranteed to start out at zero; it could start out at-123456
for all you know, and then you'd be accessing an invalid memory address. EDIT: Misread the do-while loop. Ignore this paragraph.At second glance, I would check if
h->keys[p]
is a null-terminated string -strcmp
goes on reading values until it hits a zero byte; if there's no such byte, it can keep on going until it hits an invalid memory address.