Skip to main content
Detecting and Fixing Memory Leaks with Valgrind
  1. Posts/

Detecting and Fixing Memory Leaks with Valgrind

·3 mins·
Hisam Mehboob
Author
Hisam Mehboob
metaphysically displaced person
Table of Contents

Introduction
#

A memory leak occurs when a program allocates memory dynamically (e.g., using malloc) and fails to release it using free. This leftover allocation can lead to wasted memory resources, eventually causing slowdowns or system crashes in long-running programs.

Valgrind is a powerful command-line tool available on Linux systems. It helps developers detect:

  • Memory leaks
  • Invalid memory access
  • Uninitialized memory usage
  • Mismatched memory management

In this guide, we’ll walk through examples in C to learn how to detect and fix memory leaks using Valgrind.


Installing Valgrind
#

On Arch Linux
#

sudo pacman -S valgrind

On Ubuntu/Debian
#

sudo apt install valgrind

On Fedora
#

sudo dnf install valgrind

Troubleshooting: Valgrind “cannot find mandatory redirection” on Arch Linux
#

If you run Valgrind and get an error like:

valgrind: Fatal error at startup: a function redirection

valgrind: which is mandatory for this platform-tool combination

valgrind: cannot be set up.

…you might be running a 32-bit executable on a 64-bit Arch Linux system.

Why this happens
#

Valgrind needs to hook into low-level glibc functions from your binary’s architecture.
If your binary is 32-bit, Arch requires the 32-bit glibc runtime (lib32-glibc).
Without it, Valgrind can’t find the right function symbols and quits.

Fix
#

Install the 32-bit glibc package:

sudo pacman -S lib32-glibc

After installation, re-run:

valgrind ./your-binary

and it should work.

Ubuntu/Debian equivalent: sudo apt install libc6-dbg:i386


Basic Example: Hello World
#

Code
#

#include <stdio.h>

int main() {
    printf("Hello World\n");
    return 0;
}

Compile and Run
#

gcc main.c -o main.out
./main.out

Run with Valgrind
#

valgrind ./main.out

You should see no errors or memory leaks in the output.


Introducing a Memory Leak
#

Static Allocation (Safe)
#

#include <stdio.h>

int main() {
    char str[20] = "Hello";
    printf("%s\n", str);
    return 0;
}

This uses stack memory, so Valgrind will report no leaks.

Dynamic Allocation (With Leak)
#

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char *str = malloc(20);
    strcpy(str, "Hello");
    printf("%s\n", str);
    return 0; // Forgot to free memory
}

Valgrind Output
#

valgrind ./main.out

You should see:

definitely lost: 20 bytes in 1 blocks


Fixing the Memory Leak
#

Add free(str); before returning:

free(str);

Fixed Code
#

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main() {
    char *str = malloc(20);
    strcpy(str, "Hello");
    printf("%s\n", str);
    free(str);
    return 0;
}

Detailed Valgrind Options
#

Use for deeper analysis:

valgrind --leak-check=full ./main.out

Or even more detailed:

valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes ./main.out

Explanation:

  • --leak-check=full: Display detailed leak info
  • --show-leak-kinds=all: Show all kinds of leaks (definitely, indirectly lost, etc.)
  • --track-origins=yes: Show where uninitialized values originate

Summary
#

  • Always free() memory allocated with malloc(), calloc(), or realloc().
  • Close all file streams with fclose().
  • Use Valgrind to identify and fix:
    • Memory leaks
    • Invalid memory writes
    • Use-after-free bugs
  • Recommended command:
    valgrind --leak-check=full --track-origins=yes ./your_program
    

Valgrind is a critical tool for writing safe, efficient, and bug-free C programs.

Related