Here is my code: I am trying to get the info of an struct and deep copy the info. But, valgrind
shows that "invalid read". I know that is I read the memory that is released. I don't know why; is anyone able to figure it out for me?
#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 --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)
I think this is actually an error report from valgrind
that you should suppress. It is ultimately a bug in the C library on your system.
The complaint is that code called from strdup()
is reading 4 bytes at an offset of 4 bytes into a block of 6 bytes that were allocated by malloc()
. Given that "kevin"
occupies 6 bytes, then I believe a memcpy()
variant has been employed by strdup()
and has been caught in the act of reading 4 bytes at a time through the data. While it is probably actually safe, technically, valgrind
is correct to complain. However, you can't do anything about that — your code is innocent, and the system library is guilty. That's the sort of thing suppressions are for!
+---+---+---+---+---+---+...+...+
| k | e | v | i | n | \0| ? | ? |
+---+---+---+---+---+---+...+...+
The fast copy is using the fact that the malloc()
'd data is 4-byte (more likely, 8-byte) aligned. It copies the 4 bytes 'k', 'e', 'v', and 'i' in one operation; it then copies the other two bytes of the string ('n', '\0') plus the two bytes that are not technically part of the allocated space in a second operation. The minimum actual allocation is probably 8 bytes on a 32-bit system; it tends to be 16-bytes on 64-bit machines. That means that the extra two bytes are part of the space reserved for the memory allocation, but valgrind
is correct to report that the code is copying outside the allocated space.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With