Valgrind memcheck无效读取大小1

时间:2017-06-15 07:44:19

标签: c valgrind memcheck

此示例可以编译并按预期工作。

1 #include  <stdlib.h>
2 #include  <stdio.h>
3 #include  <string.h>
4
5 char * getstr() {
6     return strdup("Hello");
7 }
8
9 void *memcpy2(void *dest, const void *src, size_t len)
10 {
11     char * d = dest;
12     const char * s = src;
13
14     for (size_t i = 0; i < len; i++) {
15         d[i] = s[i];
16     }
17     return dest;
18 }
19
20 int main()
21 {
22     char buf[256];
23     char *str = getstr();
24
25     memset(buf, 0, 256);
26     memcpy2(buf, str, 255);
27
28     printf("%s\n", buf);
29
30     free(str);
31     return 0;
32 }

我重新实现了memcpy以完全控制测试,使其独立于底层libc。如你所见,valgrind抱怨这个警告:

$ valgrind ./a.out 
==9479== Memcheck, a memory error detector
==9479== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==9479== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==9479== Command: ./a.out
==9479== 
==9479== Invalid read of size 1
==9479==    at 0x4006B6: memcpy2 (k.c:15)
==9479==    by 0x400731: main (k.c:26)
==9479==  Address 0x5203046 is 0 bytes after a block of size 6 alloc'd
==9479==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==9479==    by 0x4EC48D9: strdup (strdup.c:42)
==9479==    by 0x400673: getstr (k.c:6)
==9479==    by 0x4006F3: main (k.c:23)
==9479== 
Hello
==9479== 
==9479== HEAP SUMMARY:
==9479==     in use at exit: 0 bytes in 0 blocks
==9479==   total heap usage: 2 allocs, 2 frees, 1,030 bytes allocated
==9479== 
==9479== All heap blocks were freed -- no leaks are possible
==9479== 
==9479== For counts of detected and suppressed errors, rerun with: -v

我不明白为什么会出现“无效读取大小1”的消息。对我来说根本没有意义。你们有些人可以解释这段代码有什么问题吗?提前谢谢!

2 个答案:

答案 0 :(得分:3)

[...]
for (size_t i = 0; i < len; i++) {
15         d[i] = s[i];
16     }
[...]

此处len为255,但s指向的字符串长度小于255,因此您将离开数组。您可以使用'\0'放置的strdup()来避免此错误。

答案 1 :(得分:2)

main中,str变量指向六个字节长度的内存区域(字符串"Hello"是字符串中的五个字符加上终结符, strdup将分配strlen("Hello") + 1个字节)。超出界限会导致未定义的行为

你想要从这个六字节区域读取 255 字节,你就会超出界限。