将字符附加到 C 字符串时,Valgrind 无效 read/write
Valgrind invalid read/write when appending a character to a C string
我正在尝试解析一个字符串(大小 运行 从一篇文章到整本书),并构建一个临时链表来存储每个单独的单词,由任何空白字符分隔。我编写了自己的 charAppend()
函数,因为我认为我不能使用 strcat()
并传入 char* str
和 char c
作为参数。最终我的目标是将这个链接的单词列表组织成一个散列 table,当我尝试以 <word>:<number of occurrences>
和 printf
的格式输出散列 table 内容时,我出现段错误。 printf
的参数在 gdb 上似乎没问题,但是当我 运行 valgrind 时,我在 charAppend()
函数中得到了很多 Invalid write of size 1
和 Invalid read of size 1
。我不明白这里发生了什么,因为逐步使用 gdb 并没有给我太多信息。
我的charAppend()
函数:
//str is my current word, and c is the character I'm trying to append
char* charAppend(char* str, char c) {
int length = 0;
if (str != NULL) {
length = strlen(str);
str[length] = c;
str = realloc(str, length+1);
str[length+1] = '[=11=]';
}
else {
str = malloc(2); //1 for c, 1 for [=11=]
str[0] = c;
str[1] = '[=11=]';
}
return str;
}
下面是一些错误消息:
第 191 行是 str[length+1] = '[=25=]';
% valgrind --leak-check=full --track-origins=yes test_wc wc-small.txt
==21794== Memcheck, a memory error detector
==21794== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==21794== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==21794== Command: test_wc wc-small.txt
==21794==
==21794== Invalid write of size 1
==21794== at 0x109528: charAppend (wc.c:191)
==21794== by 0x108EB5: wc_init (wc.c:47)
==21794== by 0x108DAB: main (test_wc.c:47)
==21794== Address 0x54db1e2 is 0 bytes after a block of size 2 alloc'd
==21794== at 0x4C2DDCF: realloc (vg_replace_malloc.c:785)
==21794== by 0x109513: charAppend (wc.c:190)
==21794== by 0x108EB5: wc_init (wc.c:47)
==21794== by 0x108DAB: main (test_wc.c:47)
==21794==
==21794== Invalid read of size 1
==21794== at 0x4C2EDB4: strlen (vg_replace_strmem.c:454)
==21794== by 0x1094E5: charAppend (wc.c:188)
==21794== by 0x108EB5: wc_init (wc.c:47)
==21794== by 0x108DAB: main (test_wc.c:47)
==21794== Address 0x54db1e2 is 0 bytes after a block of size 2 alloc'd
==21794== at 0x4C2DDCF: realloc (vg_replace_malloc.c:785)
==21794== by 0x109513: charAppend (wc.c:190)
==21794== by 0x108EB5: wc_init (wc.c:47)
==21794== by 0x108DAB: main (test_wc.c:47)
至少还有 10 条这样的错误消息,一些 Conditional jump or move depends on uninitialised value(s)
是第 190 行的结果,str = realloc(str, length+1);
还有一些可能是我试图打印哈希 table 内容,我什至不明白。
==21794== Invalid read of size 8
==21794== at 0x1092CE: wc_output (wc.c:124)
==21794== by 0x108DD1: main (test_wc.c:51)
==21794== Address 0xffefffe20 is on thread 1's stack
==21794== 1680 bytes below stack pointer
==21794==
==21794== Invalid read of size 8
==21794== at 0x1092EA: wc_output (wc.c:125)
==21794== by 0x108DD1: main (test_wc.c:51)
==21794== Address 0xffefffe20 is on thread 1's stack
==21794== 1680 bytes below stack pointer
我的猜测是我对 C 字符串(尤其是修改它们)的工作方式没有正确的理解(自从我参加入门级别的 C 课程以来已经有 2 年了),但是对发生或可能发生的事情有任何帮助是错误的,将不胜感激有关如何调试这些的建议!
如果有帮助,我可以 post 更多代码,但我认为 charAppend()
是主要嫌疑人。
这部分有多个错误:
length = strlen(str);
str[length] = c;
str = realloc(str, length+1);
str[length+1] = '[=10=]';
1) strlen
而不是 给你分配的内存量。它给出的数量 减去 1。这是因为 strlen
不包括字符串终止符。所以你的realloc
是错误的。
2) 从不realloc
直接进入目标指针。 realloc
可能 return NULL
所以试试看:
length = strlen(str);
char * tmp = realloc(str, length+2); // note +2
if (tmp == NULL) exit(1); // bad error
str = tmp;
str[length] = c;
str[length+1] = '[=11=]';
我正在尝试解析一个字符串(大小 运行 从一篇文章到整本书),并构建一个临时链表来存储每个单独的单词,由任何空白字符分隔。我编写了自己的 charAppend()
函数,因为我认为我不能使用 strcat()
并传入 char* str
和 char c
作为参数。最终我的目标是将这个链接的单词列表组织成一个散列 table,当我尝试以 <word>:<number of occurrences>
和 printf
的格式输出散列 table 内容时,我出现段错误。 printf
的参数在 gdb 上似乎没问题,但是当我 运行 valgrind 时,我在 charAppend()
函数中得到了很多 Invalid write of size 1
和 Invalid read of size 1
。我不明白这里发生了什么,因为逐步使用 gdb 并没有给我太多信息。
我的charAppend()
函数:
//str is my current word, and c is the character I'm trying to append
char* charAppend(char* str, char c) {
int length = 0;
if (str != NULL) {
length = strlen(str);
str[length] = c;
str = realloc(str, length+1);
str[length+1] = '[=11=]';
}
else {
str = malloc(2); //1 for c, 1 for [=11=]
str[0] = c;
str[1] = '[=11=]';
}
return str;
}
下面是一些错误消息:
第 191 行是 str[length+1] = '[=25=]';
% valgrind --leak-check=full --track-origins=yes test_wc wc-small.txt
==21794== Memcheck, a memory error detector
==21794== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==21794== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==21794== Command: test_wc wc-small.txt
==21794==
==21794== Invalid write of size 1
==21794== at 0x109528: charAppend (wc.c:191)
==21794== by 0x108EB5: wc_init (wc.c:47)
==21794== by 0x108DAB: main (test_wc.c:47)
==21794== Address 0x54db1e2 is 0 bytes after a block of size 2 alloc'd
==21794== at 0x4C2DDCF: realloc (vg_replace_malloc.c:785)
==21794== by 0x109513: charAppend (wc.c:190)
==21794== by 0x108EB5: wc_init (wc.c:47)
==21794== by 0x108DAB: main (test_wc.c:47)
==21794==
==21794== Invalid read of size 1
==21794== at 0x4C2EDB4: strlen (vg_replace_strmem.c:454)
==21794== by 0x1094E5: charAppend (wc.c:188)
==21794== by 0x108EB5: wc_init (wc.c:47)
==21794== by 0x108DAB: main (test_wc.c:47)
==21794== Address 0x54db1e2 is 0 bytes after a block of size 2 alloc'd
==21794== at 0x4C2DDCF: realloc (vg_replace_malloc.c:785)
==21794== by 0x109513: charAppend (wc.c:190)
==21794== by 0x108EB5: wc_init (wc.c:47)
==21794== by 0x108DAB: main (test_wc.c:47)
至少还有 10 条这样的错误消息,一些 Conditional jump or move depends on uninitialised value(s)
是第 190 行的结果,str = realloc(str, length+1);
还有一些可能是我试图打印哈希 table 内容,我什至不明白。
==21794== Invalid read of size 8
==21794== at 0x1092CE: wc_output (wc.c:124)
==21794== by 0x108DD1: main (test_wc.c:51)
==21794== Address 0xffefffe20 is on thread 1's stack
==21794== 1680 bytes below stack pointer
==21794==
==21794== Invalid read of size 8
==21794== at 0x1092EA: wc_output (wc.c:125)
==21794== by 0x108DD1: main (test_wc.c:51)
==21794== Address 0xffefffe20 is on thread 1's stack
==21794== 1680 bytes below stack pointer
我的猜测是我对 C 字符串(尤其是修改它们)的工作方式没有正确的理解(自从我参加入门级别的 C 课程以来已经有 2 年了),但是对发生或可能发生的事情有任何帮助是错误的,将不胜感激有关如何调试这些的建议!
如果有帮助,我可以 post 更多代码,但我认为 charAppend()
是主要嫌疑人。
这部分有多个错误:
length = strlen(str);
str[length] = c;
str = realloc(str, length+1);
str[length+1] = '[=10=]';
1) strlen
而不是 给你分配的内存量。它给出的数量 减去 1。这是因为 strlen
不包括字符串终止符。所以你的realloc
是错误的。
2) 从不realloc
直接进入目标指针。 realloc
可能 return NULL
所以试试看:
length = strlen(str);
char * tmp = realloc(str, length+2); // note +2
if (tmp == NULL) exit(1); // bad error
str = tmp;
str[length] = c;
str[length+1] = '[=11=]';