Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

invalid read memory - valgrind

Tags:

c

valgrind

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?

Code

#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 report

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)
like image 959
kevin Avatar asked Dec 28 '13 04:12

kevin


1 Answers

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.

like image 153
Jonathan Leffler Avatar answered Sep 19 '22 23:09

Jonathan Leffler