Watchdog wraps dynamic memory functions (malloc, calloc, realloc, free) and
tracks all memory activity at runtime:
- Memory Leak Detection
- Buffer Overflows / Out-of-Bounds Access
- Double Free Detection
- Thread Safe
- Verbose Logging with Optional File Output
- Minimal Integration – Just One Header and One C File
YouTube - Stop Memory Leaks In C With Watchdog
#define WATCHDOG_ENABLE
#include "watchdog.h"
#include <stdio.h>
#include <stdlib.h>
int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) {
bool enable_verbose_log = true;
bool log_to_file = false;
bool enable_color_output = true;
w_init(enable_verbose_log, log_to_file, enable_color_output);
int *buffer = malloc(sizeof *buffer * 1024);
free(buffer);
return EXIT_SUCCESS;
}Include watchdog.h and watchdog.c in your project.
Then #include watchdog.h in a source/header file and pass flag -DWATCHDOG_ENABLE to
the CFLAGS of your build system to enable the debugger or add #define WATCHDOG_ENABLE
to a file.
Verbose logging is on by default, log to file is off by default, and color output is off by default.
static bool verbose_log = true;
static bool log_to_file = false;
static bool color_output = false;To customize the defaults, pass appropriate boolean to w_init.
bool enable_verbose_log = true;
bool log_to_file = false;
bool enable_color_output = true;
w_init(enable_verbose_log, log_to_file, enable_color_output);Enabling log_to_file will direct log output to a log file named watchdog.log.
Color output is turned off if log_to_file is enabled regardless of the
enable_color_output variable value.
If enable_verbose_log is set to false, only errors will be logged.
Code samples are located in a dedicated examples/ folder.
void malloc_example(void) {
size_t count = 5;
int *buffer = malloc(sizeof *buffer * 5);
for (size_t i = 0; i < count; i++) {
buffer[i] = -(i - count) * count;
}
for (size_t i = 0; i < count; i++) {
printf("%d ", buffer[i]);
}
putchar('\n');
free(buffer);
buffer = NULL;
}void realloc_example(void) {
short *buffer = malloc(34222);
buffer = realloc(buffer, 2342);
buffer = realloc(buffer, 2342342);
buffer = realloc(buffer, 2);
buffer = realloc(buffer, 10);
buffer = realloc(buffer, 0);
free(buffer);
buffer = NULL;
}void calloc_example(void) {
// Demonstrates correct usage of calloc
size_t count = 5;
int *buffer = calloc(count, sizeof *buffer);
for (size_t i = 0; i < count; i++) {
printf("%d ", buffer[i]); // should output 0
}
putchar('\n');
free(buffer);
buffer = NULL;
}void free_example(void) {
// Demonstrates correct usage of free
size_t count = 5;
short int *buffer0 = malloc(sizeof *buffer0 * count);
unsigned char *buffer1 = calloc(count, sizeof *buffer1);
long double *buffer2 = realloc(buffer2, sizeof *buffer2 * count);
free(buffer1);
buffer1 = NULL;
free(buffer2);
buffer2 = NULL;
free(buffer0);
buffer1 = NULL;
}void leak_example(void) {
unsigned long long int *buffer = malloc(sizeof *buffer * 20);
// intentionally not calling free
// watchdog will detect this and report it
}void overflow_example(void) {
char *buffer = malloc(sizeof *buffer * 10);
strcpy(buffer, "This will overflow"); // out-of-bounds write
// of buffer overflows will be detected with using canary values
}void double_free_example(void) {
char **buffer = malloc(sizeof *buffer * 20);
free(buffer);
free(buffer); // triggers a double-free error
}void invalid_free_example(void) {
float *buffer;
free(buffer); // will trigger an error since buffer wasn't allocated
}Interested in contributing? Please see our Contributing Guide for guidelines on how to help improve Watchdog.
This project is licensed under the MIT License.
No. It's intended for development/debug builds.
No. It only monitors dynamic memory (heap).
POSIX-compliant systems (Linux, macOS). Windows support is limited (for now).








