Finding Leaks With Mtrace in Linux-Free Embedded Linux Course In Hyderabad

PREV_LEC | NEXT_LEC

Finding Leaks With Mtrace

Tracing malloc/free calls with glibc’s built-in leak tracer — free embedded linux course

Once you can read a process’s memory footprint (covered earlier in this free embedded linux course), the next question is: which line of code is leaking? mtrace is glibc’s own built-in answer — no extra package, no emulation, just a small hook you add to your own source. This lecture builds an original demo with a deliberate leak and walks through catching it.

Keywords covered

mtrace glibc MALLOC_TRACE memory leak debugging free embedded linux course

What You Will Learn

  • How glibc’s malloc hooks let you trace every allocation without a debugger
  • How to enable mtrace with two lines of code and one environment variable
  • How to read the resulting trace log with the mtrace command
  • The key limitation of mtrace, and when to reach for Valgrind instead (next lecture)

Prerequisites

You need a glibc-based toolchain (mtrace is a glibc feature, not available on musl-based rootfs images) and basic familiarity with C and gcc.

How mtrace Works

glibc’s memory allocator supports installing hooks around malloc(), free(), realloc(), and related calls. The mtrace() function, declared in <mcheck.h>, installs exactly such hooks: from the point you call it, every allocation and every free is logged in plain ASCII to whichever file path is named by the MALLOC_TRACE environment variable. If that variable is unset, or the file can’t be opened, the hooks are simply never installed and your program runs unaffected — meaning it is safe to leave the call compiled in.

Because it logs every call rather than sampling, mtrace can tell you exactly which allocations were never matched by a corresponding free() — but only once the traced program has actually exited, since that is when it writes and closes the trace file.

mtrace Workflow
1. Program calls mtrace() near startup 2. MALLOC_TRACE=path/to/log set before running 3. Every malloc/free/realloc call logged to that file 4. Program exits -> log file is finalized 5. `mtrace <binary> <log>` cross-references log with source lines 6. Output: list of allocations never freed, with file:line

Original Demo: A Deliberate Leak

This demo (named ep_leakdemo, not reused from any book) allocates a small linked list, frees most of it correctly, but deliberately drops one node on the floor — a realistic, minimal leak pattern:

/* ep_leakdemo.c - a small, deliberate leak for mtrace to catch */
#include <mcheck.h>
#include <stdio.h>
#include <stdlib.h>

struct ep_node {
    int value;
    struct ep_node *next;
};

int main(void)
{
    mtrace();

    struct ep_node *head = NULL;
    for (int i = 0; i value = i;
        n->next = head;
        head = n;
    }

    /* Correctly free 4 of the 5 nodes ... */
    struct ep_node *cur = head;
    for (int i = 0; i next;
        free(tmp);
    }
    /* ... but 'cur' (the 5th node) is never freed - the leak */

    printf("ep_leakdemo finished (one node intentionally leaked)\n");
    return 0;
}

Building And Tracing It

Build with debug symbols so the trace can point back to source lines, then run with MALLOC_TRACE set:

$ gcc -g -Wall -o ep_leakdemo ep_leakdemo.c
$ export MALLOC_TRACE=ep_leakdemo.trace
$ ./ep_leakdemo
ep_leakdemo finished (one node intentionally leaked)
$ mtrace ep_leakdemo ep_leakdemo.trace

Expected output — mtrace correctly isolates the single unfreed node and even points at the exact source line of the leaking malloc() call:

Memory not freed:
-----------------
           Address     Size     Caller
0x0000560f2a1b32a0      0x10  at /home/ravi/ep_leakdemo.c:17

The Key Limitation

mtrace only reports leaks after the traced program exits — it cannot tell you about a leak while a long-running daemon is still alive. For a service that is expected to run for weeks on an embedded board, that means you either need to trigger a controlled shutdown to get a report, or reach for a tool that inspects a live process — which is exactly what the next lecture’s tool, Valgrind, does not solve either (it also needs the program to run under it from the start), but does give richer live diagnostics along the way.

mtrace At A Glance

AspectDetail
Requiresglibc (not musl); one function call + one env var
OverheadVery low — just hook bookkeeping
Reports leaksOnly after the process exits
Best forShort-lived tools, unit tests, CI leak checks

Common Mistakes

  • Forgetting to build with -g — without debug symbols, mtrace can still report addresses but not source file:line.
  • Not exporting MALLOC_TRACE before running — the hooks silently never install, and you get an empty, misleadingly “clean” report.
  • Expecting mtrace to work on musl-based embedded rootfs — mtrace is a glibc-specific extension.

Best Practices

  • Wire mtrace() into unit tests or CI runs for short-lived embedded utilities — it costs nothing when MALLOC_TRACE is unset in production.
  • Always build the traced binary with -g so leak reports include real source locations.
  • Treat mtrace as your first, cheapest check before reaching for Valgrind’s heavier emulation.

Summary And Key Takeaways

mtrace is a zero-dependency, glibc-native way to catch unfreed allocations, driven by one function call and one environment variable, but it only reports once the process has exited. It is ideal for short-lived embedded tools and CI; for long-running daemons or richer diagnostics, the next lecture covers Valgrind.

Conclusion

mtrace should be the first tool you reach for when debugging a suspected leak in any glibc-based embedded program, precisely because it needs nothing beyond what is already in your toolchain — a useful habit to build early in any free embedded linux course of study.

FAQ

What header do I need to use mtrace?

Include <mcheck.h> and call mtrace() near the start of main() before any allocations you want traced.

How do I enable tracing without recompiling?

Set the MALLOC_TRACE environment variable to a writable file path before running the already-instrumented binary.

Does mtrace work on musl libc?

No, mtrace is a glibc-specific extension and is not available on musl-based embedded rootfs images.

Can mtrace report leaks while the program is still running?

No, it writes and finalizes its trace log only when the traced program exits.

Why does my mtrace report show no leaks even though I know there’s one?

Most commonly the MALLOC_TRACE variable was not exported before running, so the hooks were never installed.

Do I need special compiler flags for mtrace to work?

mtrace itself needs none, but build with -g so leak reports include source file and line numbers.

Continue The Free Embedded Linux Course

Next up: catching leaks with Valgrind, including live processes and richer diagnostics.

Next Lecture Course Index
PREV_LEC | NEXT_LEC

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *