将字符附加到C字符串时Valgrind无效的读/写

时间:2018-09-21 16:45:21

标签: c gdb valgrind

我试图解析一个字符串(大小从文章到整本书),并建立一个临时链接列表来存储每个单独的单词,用任何空格字符分隔。我写了自己的charAppend()函数,因为我认为我不能使用strcat()并传入char* strchar c作为参数。最终,我的目标是将单词的链接列表组织到哈希表中,当我尝试使用<word>:<number of occurrences>printf格式输出哈希表内容时,出现了段错误。 printf的参数在gdb上似乎没问题,但是当我运行valgrind时,我的Invalid write of size 1函数中有很多Invalid read of size 1charAppend()。我不明白这里发生了什么,因为逐步使用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] = '\0';
    }
    else {
        str = malloc(2); //1 for c, 1 for \0
        str[0] = c;
        str[1] = '\0';
    }
    return str;
}

以下是一些错误消息:

第191行是str[length+1] = '\0';

% 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);,还有一些可能是我尝试打印这些错误消息的结果哈希表的内容,我什至不明白。

==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年),但是对所走或可能出错的任何帮助,并提供有关如何调试这些建议的建议!

如果有帮助,我可以发布更多代码,但是我认为charAppend()是主要的嫌疑人。

1 个答案:

答案 0 :(得分:1)

这部分有多个错误:

    length = strlen(str);
    str[length] = c;
    str = realloc(str, length+1);
    str[length+1] = '\0';

1)strlen不会给您分配的内存量。得出的金额为减1 。这是因为strlen不包含字符串终止符。因此,您的realloc是错误的。

2)永远不要realloc直接进入目标指针。 realloc可能返回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] = '\0';