cvalgrindmemcheck

Why is valgrind memcheck not finding errors?


I havent used valgrind before but I think it should detect some memory errors.

My code:

#include <stdio.h>
unsigned int a[2];

int main()
{
    a[-1] = 21;

    printf("%d,", a[-1]);

    return 1;
}

As you can see, I am accessing a[-1] which I should not.

How am I using valgrind?

I am compiling with gcc -g -O0 codeFile.c

And executing: valgrind -s ./a.out

Result is:

==239== Memcheck, a memory error detector

==239== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.

==239== Using Valgrind-3.16.0.GIT and LibVEX; rerun with -h for copyright info

==239== Command: ./a.out

==239== 21,==239==

==239== HEAP SUMMARY:

==239== in use at exit: 0 bytes in 0 blocks

==239== total heap usage: 1 allocs, 1 frees, 1,024 bytes allocated

==239==

==239== All heap blocks were freed -- no leaks are possible

==239==

==239== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Shouldnt valgrind find these error, or am I using it wrong?

EDIT: It seems that valgrind memcheck does not do anything for global variables and as suggested in the answers/comments that it should work with indexes further from the pointer, therefore: I removed the global declaration and added it insude main, and accessed a[-10] instead of a[1]. Same behaviour.

int main()
{
    unsigned int a[2];
    a[-10] = 21;

    printf("%d,", a[-10]);

    return 1;
}

It actually throws error if I use a[-100] though. Whats the deal?

EDIT 2

Furthermore, why this has no errors

while (i <= 2)
    {
        j = a[i];       
        i++;
    }

But this does

while (i <= 2)
    {
        printf("%d,", a[i]);        
        i++;
    }

Solution

  • Valgrind usually can't find memory errors where the memory being modified is at a negative offset from the current stack pointer or memory that coincides with another variable in memory.

    For example, if a was on the stack, a[3] would trigger memcheck. a[-1] would not, because that, for all Valgrind knows, could easily be valid memory.

    To expand on that, here's a quote from the documentation with my emphasis added:

    In this example, Memcheck can't identify the address. Actually the address is on the stack, but, for some reason, this is not a valid stack address -- it is below the stack pointer and that isn't allowed.

    This quote is actually partially incorrect; when it says "below the stack pointer" it really means at a positive offset from the stack pointer, or interfering with another function's stack memory.

    I should also note that (from your second edit) Valgrind doesn't actually complain until the value is used in some meaningful way. Assignment is, in Valgrind's eyes, not using the value in a meaningful way. Here's another quote to back that up with my emphasis added:

    It is important to understand that your program can copy around junk (uninitialised) data as much as it likes. Memcheck observes this and keeps track of the data, but does not complain. A complaint is issued only when your program attempts to make use of uninitialised data in a way that might affect your program's externally-visible behaviour.

    Because a is a global variable, you'll have a hard time trying to check the memory of it. One Valgrind tool I've used before that deals with this is exp-sgcheck (experimental static and global variable check), although I've found it to be unreliable (most likely due to it being experimental).

    An easier and better way to detect these would be to enable compiler warnings or use a static analyzer (my favorite is LLVM's scan-build).