【C语言】堆内存调试追踪

本文介绍了一个C/C++库BTracer,它提供了内存管理功能,包括动态内存分配、重分配和跟踪。通过`malloc`、`realloc`和`free`操作,BTracer记录了内存使用情况,并能在`btracer_trace`函数中生成详细的内存使用报告。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
#include <termios.h>
#include "string.h"
#include "debug.h"
#include "btracer.h"

void * btracer_malloc(int size, const char *moudle, int line);
void btracer_free(void *p);
 
static mem_header_t s_mem_list_head = 
{
    .magic_number = MEM_DEBUG_MAGIC_NUMBER,
    .next = NULL,
    .prev = NULL,
    .size = 0,
    .comment = "HEAD",
    .line = 0,
};

static int block_list_insert(mem_header_t *header)
{
    if (!header) {
        return -1;
    }

    // TODO: thread safe operations
    // mutex_lock

    mem_header_t *p = s_mem_list_head.next;
    s_mem_list_head.next = header;
    header->next = p;
    header->prev = &s_mem_list_head;
    if (header->next) {
        header->next->prev = header;
    }

    // TODO: thread safe operations
    // mutex_unlock

    return 0;
}

static int block_list_delete(mem_header_t *header)
{
    if (!header) {
        return -1;
    }
    // DUDO_LOGI("%.8X\n", header);

    // TODO: thread safe operations
    // mutex_lock

    if (header->prev) {
        header->prev->next = header->next;
    }

    if (header->next) {
        header->next->prev = header->prev;
    }

    // TODO: thread safe operations
    // mutex_unlock

    return 0;
}
 
void * btracer_malloc(int size, const char *moudle, int line)
{
    if (!size) {
        return NULL;
    }

    mem_header_t *header = malloc(size + sizeof(mem_header_t));

    if (header) {
        header->magic_number = MEM_DEBUG_MAGIC_NUMBER;
        header->next = NULL;
        header->prev = NULL;
        header->size = size;
        header->comment = moudle;
        header->line = line;

        block_list_insert(header);

        // DUDO_LOGI("size:%d, comment:%s, line:%d",
        //             header->size, header->comment, header->line);
        // DUDO_LOGI("header:%.8X\n", header);

        return (void *)((char *)header + sizeof(mem_header_t));
    } else {
        return NULL;
    }

}

void * btracer_realloc(void *p, int size, const char *moudle, int line)
{
    if (!size) {
        return NULL;
    }

    mem_header_t *header = (mem_header_t *)((unsigned long)p - sizeof(mem_header_t));
    // 1. remove old block from list, this operation has to be performed befor realloc executed,
    // because new address is different with old address.
    block_list_delete(header);
    
    // 2. reallocate memory space, please remember that new address is different with old address.
    void *new = realloc(header, size + sizeof(mem_header_t));
    if (!new) {
        // 3. if realloc failed, insert old block to block list.
        block_list_insert(header);
        return NULL;
    }

    // 4. create new block and insert into list
    header = (mem_header_t *)new;

    if (header) {
        header->magic_number = MEM_DEBUG_MAGIC_NUMBER;
        header->next = NULL;
        header->prev = NULL;
        header->size = size;
        header->comment = moudle;
        header->line = line;

        block_list_insert(header);

        return (void *)((char *)header + sizeof(mem_header_t));
    } else {
        return NULL;
    }
}

void btracer_free(void *p)
{
    if (!p) {
        return;
    }

    mem_header_t *header = (mem_header_t *)((unsigned long)p - sizeof(mem_header_t));
    // DUDO_LOGI("size:%d, comment:%s, line:%d",
    //             header->size, header->comment, header->line);
    // DUDO_LOGI("header:%.8X\n", header);

    block_list_delete(header);

    free(header);
}

void btracer_trace(void)
{
    int used_cnt = 0;
    int total_size = 0;

    mem_header_t *p = s_mem_list_head.next;
    while (p) {
        DUDO_LOGI("h:%.8X, p:%.8X, s:%4d, m:\"%16s\", l:%4d",
                    (uint32_t)p, (uint32_t)p + sizeof(mem_header_t), p->size, p->comment, p->line);

        used_cnt++;
        total_size += p->size;

        p = p->next;
    }

    DUDO_LOGI("\n");
    DUDO_LOGI("Block count:%d\n", used_cnt);
    DUDO_LOGI("Total memory size:%d\n", total_size);
    DUDO_LOGI("Total memory footprint:%d\n", total_size + used_cnt * sizeof(mem_header_t));
}

#ifndef __BTRACER_H__
#define __BTRACER_H__

#include "stdint.h"


#define MEM_DEBUG_MAGIC_NUMBER      0x55AA55AA
#define MALLOC(_SIZE)               btracer_malloc(_SIZE, __FUNCTION__, __LINE__)
#define REALLOC(_P, _SIZE)          btracer_realloc(_P, _SIZE, __FUNCTION__, __LINE__)
#define FREE(_P)                    btracer_free(_P)
 
typedef struct mem_header
{
    unsigned int magic_number;
    struct mem_header *prev;
    struct mem_header *next;
    unsigned int size;
    char *comment;
    int line;
} mem_header_t;
 
 

void * btracer_malloc(int size, const char *moudle, int line);
void btracer_free(void *p);
void btracer_trace(void);



#endif

BEDO

TODO

DONE

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值