【问题标题】:Uninitialized value from valgrind来自 valgrind 的未初始化值
【发布时间】:2015-11-13 06:15:58
【问题描述】:
==2630== Conditional jump or move depends on uninitialised value(s)
==2630==    at 0x4E82D71: vfprintf (in /usr/lib64/libc-2.21.so)
==2630==    by 0x4E88E78: printf (in /usr/lib64/libc-2.21.so)
==2630==    by 0x400C0C: searchWord (T9.c:91)
==2630==    by 0x400A0A: main (T9.c:40) 

==2114==  Uninitialised value was created by a heap allocation
==2114==    at 0x4C28C50: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==2114==    by 0x400FD1: newStr (trie_node.c:125)
==2114==    by 0x400F8C: create_trie (trie_node.c:117)
==2114==    by 0x4009D5: main (T9.c:37)

通过在 valgrind 中运行跟踪功能,我收到了上面的错误消息。我很确定我已经初始化了变量。 这是结构代码:

struct wordList* newStr(char* text) {
    char* word;
    struct wordList* tmp = (struct wordList*)malloc(sizeof(struct wordList));
    word = (char *)malloc(sizeof(char) * strlen(text) + 1);
    strncpy(word, text, strlen(text));
    tmp->str = word;
    tmp->next = NULL;
    return tmp;
}

以及 T9.c 第 91 行周围的代码:

struct wordList* cur;
if (cur && invalid == 0 && flag == 0) {
  printf("\t\'%s\'\n", cur->str);
 } 

更新:

我修改 strncpy 行来自

    strncpy(word, text, strlen(text));

word = strncpy(word, text, strlen(text));

这解决了未初始化的问题,但是我收到了我不理解的新错误消息:

==3245== Invalid read of size 1
==3245==    at 0x4E82D71: vfprintf (in /usr/lib64/libc-2.21.so)
==3245==    by 0x4E88E78: printf (in /usr/lib64/libc-2.21.so)
==3245==    by 0x400C0C: searchWord (T9.c:91)
==3245==    by 0x400A0A: main (T9.c:40)
==3245==  Address 0x51f7d45 is 0 bytes after a block of size 5 alloc'd
==3245==    at 0x4C28C50: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==3245==    by 0x400FC1: newStr (trie_node.c:124)
==3245==    by 0x400F80: create_trie (trie_node.c:117)
==3245==    by 0x4009D5: main (T9.c:37)

【问题讨论】:

  • text 的值是多少?
  • 你可以省略sizeof(char),因为那将是1,但如果你想明确一点,请在strlen(text) + 1周围加上括号。另外,不要强制转换 malloc 的返回值:void * 会自行找到您的char *word
  • 请把图片中的代码贴出来,去掉图片。
  • strncpy 有一个更安全的变体:它称为strcpy。在这里使用它可以避免这个错误。
  • @M.M u 刚刚解决了我的问题

标签: c memory struct valgrind


【解决方案1】:

我需要查看更多代码,但虽然我不确定这正是 valgrind 所抱怨的,但您的代码确实存在一个重大错误:

strncpy(word, text, strlen(text));

你不是以空值终止你的字符串,你只是在复制实际的字符。这特别有趣,因为有一个函数已经负责分配正确的内存量和复制字符串:strdup

还有强制警告停止转换malloc 的返回值。

【讨论】:

  • Null 终止你的字符串。我已经提过了,请看回复。
  • C 中没有名为strdup 的函数,它是非标准的。所以没有理由对此沾沾自喜。
  • 就像 Lundin 说的,C 中没有 strdupIf you need it, you need to write it yourself
【解决方案2】:

您必须查看完整的错误(不仅仅是第二个错误)。根据经验,您应该从上到下阅读错误,因为后续错误可能是前者的结果(或对前者的解释)。第二条消息只是告诉您malloc 分配的内存没有初始化,这与预期的一样 - 它只是对第一条的修正。

错误在于当您使用分配的空间时没有用有用的东西填充它。问题出在新发布的代码上,cur->str指向的块可能是未初始化的。

这个错误有点棘手,因为你使用了strncpy。它只会复制strlen(text) 字节,从而跳过空终止符。您已经为它腾出了空间,但它没有被复制,因此分配缓冲区的最后一个字节没有被初始化(当vfprintf 遍历字符串并到达空终止符应该所在的字节时会发生错误)。

要清楚 strncpy(dst, src, cnt) 的作用。它最多复制cnt 字节(包括空终止符),如果包含空终止符的src 字符串不超过cnt 字节,它将复制完整的字符串。否则它只会复制字符串的第一个 cnt 字节并且 not null 终止 dst

【讨论】:

  • cur->str在newStr方法中初始化
  • @Big_tboy 我的意思是cur->str指向的数据没有完全初始化。
  • 这就是我问这个问题的原因,显然我已经在我的 newStr 函数中初始化了这个 str
  • @Big_tboy 你已经分配了strlen(text)+1 字节,但只初始化了第一个strlen(text) 字节。应该包含空终止符的最后一个字节初始化。
猜你喜欢
  • 2014-03-21
  • 1970-01-01
  • 2022-12-04
  • 2021-01-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-15
  • 1970-01-01
相关资源
最近更新 更多