Search code examples
c++cvalgrind

Why in the following situation valgrind memcheck don't issue the overlapping error?


In Valgrind's Memcheck tool, it says

The following C library functions copy some data from one memory block to another (or something similar): memcpy, strcpy, strncpy, strcat, strncat. The blocks pointed to by their src and dst pointers aren't allowed to overlap. The POSIX standards have wording along the lines "If copying takes place between objects that overlap, the behavior is undefined." Therefore, Memcheck checks for this.

So I think if I use memcpy to copy between overlapped addresses, I can get this error from valgrind memcheck.

So I write the following code. However, either in the C++ version or the C version, I can't make valgrind memcheck for a overlap error.

int main()
{
    // The C++ version
    int * x = new int[3]{1, 2, 3};
    memcpy(x + 1, x, 2);
}

int main()
{
    // The C version 
    void * y = malloc(10);
    memset(y, 0, 10);
    memcpy(y + 1, y, 2);
}

In fact, if I run by the following command

valgrind --tool=memcheck --leak-check=full --track-origins=yes ./tt

Then I will get

==33771== Memcheck, a memory error detector
==33771== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==33771== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==33771== Command: ./tt
==33771==
==33771==
==33771== HEAP SUMMARY:
==33771==     in use at exit: 10 bytes in 1 blocks
==33771==   total heap usage: 2 allocs, 1 frees, 72,714 bytes allocated
==33771==
==33771== 10 bytes in 1 blocks are definitely lost in loss record 1 of 1
==33771==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==33771==    by 0x4006C8: main
==33771==
==33771== LEAK SUMMARY:
==33771==    definitely lost: 10 bytes in 1 blocks
==33771==    indirectly lost: 0 bytes in 0 blocks
==33771==      possibly lost: 0 bytes in 0 blocks
==33771==    still reachable: 0 bytes in 0 blocks
==33771==         suppressed: 0 bytes in 0 blocks
==33771==
==33771== For lists of detected and suppressed errors, rerun with: -s
==33771== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

I wonder why, and in what situation can valgrind output an overlap error?


Solution

  • Even with just a debug build the compiler sees that it's more efficient not to make a call to memcpy:

    https://godbolt.org/z/P9s664Gx8

    GCC is similar. I don't get a call to memcpy until 12 bytes are copied.