xur17
xur17

Reputation: 516

Using Valgrind to Debug Use After Free

I am trying to debug a use after free error in my code using Valgrind.

My code is crashing when it tries to access an object that was previously deleted. Is there some way to see who deleted the object in this case using Valgrind?

I ran Valgrind using the following option, but it only catches the crash, and shows where it occurred. I'm hoping to get details on where the object was deallocated:

valgrind --tool=memcheck

Upvotes: 4

Views: 6301

Answers (2)

Marco Leogrande
Marco Leogrande

Reputation: 8458

This is what I use in these cases:

valgrind --track-origins=yes

In case of a use-after-free, it will show you the stacktrace of the function that free'd the memory/deleted the object.

Please read the manpage of Valgrind for the caveats, specifically the ones about performance. If your issue is a concurrency problem, a slower Valgrind might change the timing properties of your program and possibly change (either reduce or increase) the probability to hit the bug.

--track-origins=<yes|no> [default: no]
    Controls whether Memcheck tracks the origin of uninitialised
    values. By default, it does not, which means that although it can
    tell you that an uninitialised value is being used in a dangerous
    way, it cannot tell you where the uninitialised value came from.
    This often makes it difficult to track down the root problem.

    When set to yes, Memcheck keeps track of the origins of all
    uninitialised values. Then, when an uninitialised value error is
    reported, Memcheck will try to show the origin of the value. An
    origin can be one of the following four places: a heap block, a
    stack allocation, a client request, or miscellaneous other sources
    (eg, a call to brk).

    For uninitialised values originating from a heap block, Memcheck
    shows where the block was allocated. For uninitialised values
    originating from a stack allocation, Memcheck can tell you which
    function allocated the value, but no more than that -- typically it
    shows you the source location of the opening brace of the function.
    So you should carefully check that all of the function's local
    variables are initialised properly.

    Performance overhead: origin tracking is expensive. It halves
    Memcheck's speed and increases memory use by a minimum of 100MB,
    and possibly more. Nevertheless it can drastically reduce the
    effort required to identify the root cause of uninitialised value
    errors, and so is often a programmer productivity win, despite
    running more slowly.

    Accuracy: Memcheck tracks origins quite accurately. To avoid very
    large space and time overheads, some approximations are made. It is
    possible, although unlikely, that Memcheck will report an incorrect
    origin, or not be able to identify any origin.

    Note that the combination --track-origins=yes and
    --undef-value-errors=no is nonsensical. Memcheck checks for and
    rejects this combination at startup.

Upvotes: 7

user823738
user823738

Reputation: 17521

Valgrind has shown you maximum it could. You need to compile your code with more debug information - then valgrind will be able to show you more information such as file, function and line.

Compile your code with -g option and rerun with valgrind. On some compilers there is also -gN where N is level of debug. But in most cases, -g is sufficient.

Upvotes: 1

Related Questions