How to Diagnose C++ Memory Leaks and Segmentation Faults for High‑Frequency Interviews

The article explains why memory leaks and segmentation faults are hard‑to‑detect hidden bugs in Linux C++ back‑end and embedded development, illustrates common causes with concrete code samples, and walks through Linux commands and tools such as top, ps, pmap, vmstat, Valgrind, AddressSanitizer, memleak and gdb to locate and fix these issues.

Deepin Linux
Deepin Linux
Deepin Linux
How to Diagnose C++ Memory Leaks and Segmentation Faults for High‑Frequency Interviews

In Linux C++ back‑end and embedded development, memory leaks and segmentation faults are the most hidden runtime errors, often appearing only after long‑running, high‑concurrency workloads.

Typical memory errors

1. Memory not released (leak)

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

void memory_leak_example() {
    int *ptr = (int *)malloc(sizeof(int));
    // missing free(ptr)
}

int main() {
    for (int i = 0; i < 1000; i++) {
        memory_leak_example();
    }
    return 0;
}

The loop allocates an int on each iteration without freeing it, causing the resident set size (RSS) to grow until the process is OOM‑killed.

2. Wild pointer access

#include <iostream>

void wild_pointer_example() {
    int *ptr; // uninitialized
    std::cout << *ptr << std::endl; // undefined behavior

    int *ptr2 = new int(10);
    delete ptr2;
    std::cout << *ptr2 << std::endl; // use‑after‑free
}

int main() {
    wild_pointer_example();
    return 0;
}

Dereferencing an uninitialized pointer and a pointer after delete both produce undefined behavior that can crash the program.

3. Double free

#include <iostream>

void double_free_example() {
    int *ptr = new int(10);
    delete ptr;
    delete ptr; // double free, undefined behavior
}

int main() {
    double_free_example();
    return 0;
}

Calling delete twice corrupts the allocator’s metadata and may lead to crashes or security issues.

4. Buffer overflow

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

void buffer_overflow_example() {
    char buffer[5];
    char *str = "Hello, World!";
    strcpy(buffer, str); // overflow
    printf("%s
", buffer);
}

int main() {
    buffer_overflow_example();
    return 0;
}

Copying a longer string into a 5‑byte array overwrites adjacent memory, which can cause crashes or be exploited.

Locating anomalies at runtime

top – real‑time view of per‑process RES and %MEM; sort by memory usage.

ps aux – shows VSZ, RSS and %MEM for all processes; combine with grep to filter.

pmap <pid> – detailed memory map of a process, useful for spotting unusually large anonymous regions.

vmstat – system‑wide memory statistics; a steady decline of free and rise of swap often indicates a leak.

Deep analysis tools

Valgrind – install via package manager (e.g., sudo apt-get install valgrind). Run with valgrind --leak-check=full ./test; add --track-origins=yes to trace uninitialized reads. Sample output:

==12345== 1024 bytes in 1 blocks are definitely lost in loss record 1 of 1
==12345==    at 0x483B7F3: malloc (vg_replace_malloc.c:309)
==12345==    by 0x4012A6: process_order (order.c:15)
==12345==    by 0x4015C3: main (main.c:42)

AddressSanitizer (ASan) – compile with -fsanitize=address -g -O0 (or add the flags in CMakeLists.txt). Example compile command:

g++ -fsanitize=address -g -O0 main.cpp -o main

When a violation occurs, ASan aborts and prints a report, e.g.:

==12345==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000ef84 READ of size 4
#0 0x4dd123 in process_array(int*) /path/to/main.cpp:15
#1 0x4dd2a7 in main /path/to/main.cpp:25

memleak – eBPF‑based tracer. Typical usage:

sudo memleak -p <pid> -o | tee memory_leak.log

Or continuous monitoring:

watch -n 10 sudo memleak -p -c 20

Sample output shows top allocation stacks:

[12:34:56] Top 10 stacks with outstanding allocations:
128 bytes in 4 allocations from stack malloc+0x1a [libc] create_object+0x25 [myapp] process_request+0x67 [myapp]
512 bytes in 2 allocations from stack calloc+0x15 [libc] init_buffer+0x3e [myapp]

Analyzing a crash stack

Compile with -g to embed debug symbols.

Run gdb <executable>, then bt to print the backtrace. Example backtrace:

#0  0x0000000000401234 in function_c () at file_c.c:50
#1  0x0000000000401567 in function_b () at file_b.c:30
#2  0x000000000040189a in function_a () at file_a.c:15
#3  0x0000000000401abc in main () at main.c:10

If a core dump exists, use gdb -c core_dump_file <executable> to inspect the state at the moment of failure.

Understanding the backtrace lets you pinpoint the exact source line that caused the fault (e.g., an out‑of‑bounds array access) and correct the code.

Key takeaways

Memory leaks are forgotten heap allocations; segmentation faults are illegal virtual‑memory accesses. A combined workflow of system commands, Valgrind, AddressSanitizer and gdb can locate virtually all Linux C++ memory anomalies, enabling stable, high‑performance code.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

debuggingmemory-leakGDBvalgrindaddresssanitizersegfault
Deepin Linux
Written by

Deepin Linux

Research areas: Windows & Linux platforms, C/C++ backend development, embedded systems and Linux kernel, etc.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.