Fundamentals 9 min read

Using GDB Watchpoints to Detect Memory Modifications in C/C++ Programs

This article explains how to use GDB watchpoints to monitor specific memory locations in C/C++ programs, demonstrates setting hardware watchpoints, shows example code with a thread modifying a variable, and details the underlying CPU debug registers that enable real‑time detection of memory reads and writes.

IT Services Circle
IT Services Circle
IT Services Circle
Using GDB Watchpoints to Detect Memory Modifications in C/C++ Programs

Memory is a great helper for C/C++ programmers; the higher performance of C/C++ is partly due to manual memory management, but memory problems also cause endless headaches.

Issues such as wild pointers, out‑of‑bounds accesses, incorrect allocation or deallocation, and multithreaded reads/writes can corrupt memory, making bugs hard to locate because the program often crashes far from the actual fault.

Since these bugs stem from memory reads or writes, it would be useful to observe when a memory region is accessed or modified – and fortunately this technology already exists.

Example

In GDB you can add a watchpoint to monitor a memory region; when the region is modified the program stops, allowing you to see which line of code performed the modification.

Below is a simple C++ program that will be used for the demonstration:

#include <iostream>
#include <thread>
using namespace std;

// Thread modifies variable value
void memory_write(int* value) {
    *value = 1;
}

int main() {
    int a = 10;
    // Get address of local variable a
    int* c = &a;

    for (int i = 0; i < 100; i++) {
        a += i;
    }

    cout << a << endl;

    // Pass address of a to a thread
    thread t(memory_write, c);
    t.join();

    return 0;
}

The program creates a local variable a , obtains its address in pointer c , performs a series of additions (resulting in a = 4960), prints the value, then spawns a thread that writes 1 to a .

If later you notice that a has become 1 without obvious cause, you can use GDB to find out which code changed it.

Start Catching the Culprit

Compile the program (source file a.cc , executable a.out ) and start GDB:

$ gdb a.out
(gdb) b a.cc:20
Breakpoint 1 at 0x400f23: file a.cc, line 20.
(gdb) r
Starting program: /bin/a
Breakpoint 1, main () at a.cc:20
20          cout << a << endl;

The breakpoint stops execution at line 20. Now inspect the address of a :

(gdb) p &a
$1 = (int *) 0x7fffffffe508

We see that a resides at 0x7fffffffe508 . To have GDB continuously monitor this address, set a hardware watchpoint:

(gdb) watch *(int*)0x7fffffffe508
Hardware watchpoint 2: *(int*)0x7fffffffe508

The watch command tells GDB to watch a 4‑byte region starting at the given address (assuming int is 4 bytes).

Continue execution:

(gdb) c
Continuing.
4960

After the program reaches the watchpoint, GDB reports:

[New Thread 0x7ffff6f5c700 (LWP 531823)]
[Switching to Thread 0x7ffff6f5c700 (LWP 531823)]
Hardware watchpoint 2: *(int*)0x7fffffffe508

Old value = 4960
New value = 1
memory_write (value=0x7fffffffe508) at a.cc:8
8       }
(gdb)

GDB has identified that the thread changed the memory at 0x7fffffffe508 from 4960 to 1 at line 8 of a.cc , which is exactly where the thread writes to the variable.

How Watchpoints Work

Modern CPUs provide special debug registers (x86: DR0‑DR7) that can monitor memory addresses for reads and/or writes. Hardware watchpoints use these registers to detect accesses without slowing the program.

GDB also offers rwatch (watch reads), awatch (watch reads or writes), and watch (watch writes). When a watched event occurs, the CPU halts execution and transfers control to the debugger.

If the hardware does not support watchpoints, GDB falls back to software watchpoints, which check the condition after each executed instruction and are therefore much slower. The command set can-use-hw-watchpoints can force GDB to use one mode or the other.

Note that software watchpoints are limited in multithreaded programs because they may miss modifications performed by other threads.

That concludes the discussion on using GDB watchpoints to track memory changes; hope it helps you understand memory debugging better.

debuggingC++multithreadingMemoryGDBhardware watchpointwatchpoint
IT Services Circle
Written by

IT Services Circle

Delivering cutting-edge internet insights and practical learning resources. We're a passionate and principled IT media platform.

0 followers
Reader feedback

How this landed with the community

login 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.