【问题标题】:invalid read memory - valgrind无效的读取内存 - valgrind
【发布时间】:2013-12-28 04:14:15
【问题描述】:

这是我的代码:我正在尝试获取结构的信息并深复制该信息。但是,valgrind 显示“无效读取”。我知道那是我读取了被释放的内存。我不知道为什么;有人能帮我弄清楚吗?

代码

#include  <stdlib.h>
#include  <stdio.h>
#include  <string.h>

struct student
{
    int id;
    char *name;
    int age;
};

void get_info(struct student *dest, struct student *src)
{
    memcpy(dest,src,sizeof(struct student));
    dest->name = strdup(src->name);
}

int main()
{
    struct student foo;
    foo.id = 1001;
    foo.name = strdup("kevin");
    foo.age = 18;

    struct student bar;
    get_info(&bar, &foo);

    puts(bar.name);

    free(foo.name);
    free(bar.name);

    return 0;
}

Valgrind 报告

valgrind --tool=memcheck --leak-check=full ./test
==2130== Memcheck, a memory error detector
==2130== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==2130== Using Valgrind-3.9.0 and LibVEX; rerun with -h for copyright info
==2130== Command: ./test
==2130== 
==2130== Invalid read of size 4
==2130==    at 0x40B083B: ??? (in /lib/tls/i686/cmov/libc-2.11.1.so)
==2130==    by 0x40B04A4: strdup (in /lib/tls/i686/cmov/libc-2.11.1.so)
==2130==    by 0x80484B1: get_info (test.c:15)
==2130==    by 0x80484F8: main (test.c:26)
==2130==  Address 0x419902c is 4 bytes inside a block of size 6 alloc'd
==2130==    at 0x4026775: malloc (vg_replace_malloc.c:291)
==2130==    by 0x40B04AF: strdup (in /lib/tls/i686/cmov/libc-2.11.1.so)
==2130==    by 0x80484D8: main (test.c:22)
==2130== 
==2130== Invalid read of size 4
==2130==    at 0x40B083B: ??? (in /lib/tls/i686/cmov/libc-2.11.1.so)
==2130==    by 0x409ACE4: puts (in /lib/tls/i686/cmov/libc-2.11.1.so)
==2130==    by 0x8048504: main (test.c:28)
==2130==  Address 0x4199064 is 4 bytes inside a block of size 6 alloc'd
==2130==    at 0x4026775: malloc (vg_replace_malloc.c:291)
==2130==    by 0x40B04AF: strdup (in /lib/tls/i686/cmov/libc-2.11.1.so)
==2130==    by 0x80484B1: get_info (test.c:15)
==2130==    by 0x80484F8: main (test.c:26)
==2130== 
kevin
==2130== 
==2130== HEAP SUMMARY:
==2130==     in use at exit: 0 bytes in 0 blocks
==2130==   total heap usage: 2 allocs, 2 frees, 12 bytes allocated
==2130== 
==2130== All heap blocks were freed -- no leaks are possible
==2130== 
==2130== For counts of detected and suppressed errors, rerun with: -v
==2130== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 11 from 6)

【问题讨论】:

  • @ElliottFrisch 有趣的是,valgrind 没有为我报告任何错误。也许是未定义的行为?
  • @remyabel Yes.
  • 嗨,谢谢你们的帮助。我的环境:ubuntu 10.04 Valgrind-3.9.0 并用 gcc 4.4.3 编译。始终显示此无效的读取信息。
  • strdup 的结果应该是freeable,除非有人滚动了自己的strdup。我不得不承认我现在也没有看到 UB。
  • 无论有无免费,我都无法重现无效读取。

标签: c valgrind


【解决方案1】:

我认为这实际上是来自valgrind 的错误报告,您应该禁止。这最终是您系统上 C 库中的一个错误。

抱怨是从strdup() 调用的代码正在将4 字节偏移量读取到malloc() 分配的6 字节块中。鉴于"kevin" 占用6 个字节,那么我相信strdup() 使用了memcpy() 变体,并且在一次读取4 个字节数据的行为中被捕获。虽然它实际上可能是安全的,但从技术上讲,valgrind 抱怨是正确的。但是,您对此无能为力——您的代码是无辜的,而系统库是有罪的。这就是压制的目的!

+---+---+---+---+---+---+...+...+
| k | e | v | i | n | \0| ? | ? |
+---+---+---+---+---+---+...+...+

快速复制使用malloc()'d 数据是 4 字节(更可能是 8 字节)对齐的事实。它在一次操作中复制 4 个字节“k”、“e”、“v”和“i”;然后,它会在第二次操作中复制字符串的其他两个字节('n'、'\0')以及技术上不属于分配空间的两个字节。在 32 位系统上,最小的实际分配可能是 8 个字节;它在 64 位机器上往往是 16 字节。这意味着额外的两个字节是为内存分配保留的空间的一部分,但valgrind 报告代码正在复制到分配的空间之外是正确的。

【讨论】:

  • 哇,完全有道理。分配了 6 个字节,memcpy 实际上复制了 8 个字节(2 次,每次 4 个字节),这是 Valgrind 抱怨的,因为我“读取”了超出我分配的字节。赞赏!顺便说一句,当对象(结构)能够分配给纯 C 中的其他对象时?还是最初由设计支持?记不太清楚了。
  • 结构分配是在 1978 年第一版 K&R 出版后不久添加的;当我在 1983 年开始使用 C 时,我们使用的 C 编译器已经具有结构赋值(但并非所有 C 编译器都具有)。到 C 标准发布时(1989 年、1990 年),大多数编译器都支持结构赋值(但我在一个代码库中工作,其中包含旧世界的残余,STRUCTASG 宏仍在少数地方使用——这让我很恼火)。如果memcpy() 比结构赋值更快,那么编译器编写者在某个地方犯了一个大错误。
【解决方案2】:

这看起来像是 strdup()puts() 中的优化,它们以四个字节的块读取输入,而不是一次一个字节,但是他们小心不要写入超出结尾。只要四个字节地址对齐,这是安全的:正确对齐的读取永远不会触发硬件异常,并且由于这两个函数不会写入超出字符串的末尾,因此它们的操作是安全的,即使从语言的角度来看它是非法的。并且您可以确定这四个字节地址将正确对齐,因为它是一种优化,未对齐的读取会使代码爬行。

Valgrind 检查语言级别的正确性,而不是物理级别,因此会报告错误。所以我同意 Jonathan Leffler 的观点,即你应该压制这个“错误”,看看 cmets,似乎是由更新版本的 valgrind 自动完成的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-07-07
    • 1970-01-01
    • 2017-04-09
    • 2015-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多