C/C++ implements a simple memory leak detection tool by itself

For learning and practice, it is best to use special tools to truly detect memory leaks.

C++ Language

 

C Language

This memory leak detection tool is simple, can only detect the same module, the same thread sent memory leaks, for code debugging in the writing process has some help.If memory leaks are to be detected in an integrated or functional test, special tools are also required.

1. Undefine the identifiers malloc, free, and calloc first: It is important to note this step, otherwise the malloc, free, and calloc functions will conflict with the macros we define later in the header file
 

// Cancel macro definitions for malloc, calloc, free
#undef malloc
#undef calloc
#undef free

2. Define a one-way chain table to hold memory information

/**
 * Define a linked list node to represent a memory leak information
 */
typedef struct _mem_node
{
	void *ptr;	   // Leaked Memory Address
	size_t block;	// Leaked Memory Size
	size_t line;	// The line of code where the leak occurred
	char *filename;	// File name where the leak occurred
	struct _mem_node *next;	// Next Node Pointer
} mem_node;
 
// Define pointer to header node
mem_node *head = NULL;

3. Functions used to add nodes to a single list of chains

/**
 * Generate a node and join the list
 * @param ptr Allocated memory address
 * @param block Allocated memory unit size
 * @param line Code line number
 * @param filename File Name
 */
static void mem_node_add(void *ptr, size_t block, size_t line, char *filename)
{
	// Generate Node
	mem_node *node = malloc(sizeof(mem_node));
	node->ptr = ptr;
	node->block = block;
	node->line = line;
	node->filename = filename;
	node->next = NULL;
 
	// Join Chain Header Node
	if (head)
	{
		node->next = head;
		head = node;
	}
	else
		head = node;
}

4. Functions to delete nodes from a single list

/**
 * Delete a node from the list of chains
 * @param ptr Allocated memory address
 */
static void mem_node_remove(void *ptr)
{
	// Determine whether the header node exists
	if (head)
	{
		// Processing Header Node
		if (head->ptr == ptr)
		{
			// Get the next node of the header node
			mem_node *pn = head->next;
			// Delete Head Node
			free(head);
			// Header node pointer to next node
			head = pn;
		}
		else	// Determine if the list is empty
		{
			// Pointer to node
			mem_node *pn = head->next;
			// Pointer to previous node
			mem_node *pc = head;
			// Traverse all nodes
			while (pn)
			{
				// Gets the pointer to the next node
				mem_node *pnext = pn->next;
				if (pn->ptr == ptr)
				{
					pc->next = pnext;	// Delete current node
					free(pn);
				}
				else
					pc = pc->next;
				pn = pnext;
			}
		}
	}
}

5. Display memory leak information report

/**
 * Display memory leak information
 */
void show_block()
{
    if (head)
    {
        // Save total memory leaks
        size_t total = 0;
        // Pointer to Head Node
        mem_node *pn = head;
 
        // Output Title
        puts("\n\n-------------------------------Memory leak Report------------------------------------\n");
 
        // Traversing a list of chains
        while (pn)
        {
            mem_node *pnext = pn->next;
            // Processing File Name
            char *pfile = pn->filename, *plast = pn->filename;
            while (*pfile)
            {
                // Find the \character
                if (*pfile == '\\')
                    plast = pfile + 1;    // Get the position of the \character
                pfile++;
            }
            // Output Memory Leak Information
            printf("position:%s(%d), address:%p(%dbyte)\n", plast, pn->line, pn->ptr, pn->block);
            // Total cumulative memory leaks
            total += pn->block;
            // Delete Chain List Node
            free(pn);
            // Point to Next Node
            pn = pnext;
        }
        printf("Total memory leak:%dbyte\n", total);
    }
}

6. Define the malloc function for debugging

/**
 * malloc function for debugging
 * @param elem_size Allocate memory size
 * @param filename File Name
 * @param line Code line number
 */
void *dbg_malloc(size_t elem_size, char *filename, size_t line)
{
    void *ptr = malloc(elem_size);
    // Add the address that allocates memory to the list of chains
    mem_node_add(ptr, elem_size, line, filename);
    return ptr;
}

7. Define calloc functions for debugging

/**
 * calloc function for debugging
 * @param count Allocate the number of memory units
 * @param elem_size Memory size per unit
 * @param filename File Name
 * @param line Code line number
 */
void *dbg_calloc(size_t count, size_t elem_size, char *filename, size_t line)
{
    void *ptr = calloc(count, elem_size);
    // Add the address that allocates memory to the list of chains
    mem_node_add(ptr, elem_size * count, line, filename);
    return ptr;
}

8. Define free functions for debugging

/**
 * free function for debugging
 * @param ptr Memory address to release
 */
void dbg_free(void *ptr)
{
    free(ptr);
    // Delete Node from Chain List
    mem_node_remove(ptr);
}

The above code should be contained in a C file (e.g. memcheck.c). After completing the above steps, you can use this set of functions to detect memory leaks. You need to define the following header file, which should be include d in the C file where the above functions are written:

#ifndef _MEM_CHECK_H
#define _MEM_CHECK_H
 
#include <stdlib.h>
 
// instead of malloc
#define malloc(s) dbg_malloc(s, __FILE__, __LINE__)
 
// instead of calloc
#define calloc(c, s) dbg_calloc(c, s, __FILE__, __LINE__)
 
// instead of free
#define free(p) dbg_free(p)
 
/**
 * allocation memory
 */
void *dbg_malloc(size_t elem_size, char *filename, size_t line);
 
/**
 * allocation and zero memory
 */
void *dbg_calloc(size_t count, size_t elem_size, char *filename, size_t line);
 
/**
 * deallocate memory
 */
void dbg_free(void *ptr);
 
/**
 * show memory leake report
 */
void show_block();
 
#endif // _MEM_CHECK_H

All you need to do is include the above header file (for example, named memcheck.h) and import the C file into your project.The test code is as follows:

#ifdef DEBUG
#include "memcheck.h"
#endif
 
int main()
{
    int* p;
 
#ifdef DEBUG
    atexit(show_block); // Display memory leak report after program completion
#endif // DEBUG
    // Allocate memory and do not recycle, display memory leak Report
    p = (int*)malloc(1000);
 
    return 0;
}


Original Link:https://blog.csdn.net/mousebaby808/article/details/17212111

Tags: C

Posted on Wed, 24 Jun 2020 21:12:05 -0400 by jmakeig