结构体,指针,链表,动态分配内存--检查内存是否泄漏问题

本文介绍了一种通过封装malloc和free,利用结构体和链表来辅助检查内存泄漏的方法。创建的链表节点包含分配内存的函数名、行号、大小和地址信息。当调用自定义的SV_FREE时,会从链表中移除并释放对应的内存。这种方法不直接解决内存泄漏,而是提供一种追踪内存分配的手段。

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

目的:协助开发人员检查内存是否泄漏问题。
注意事项:不能直接解决开发人员的内存泄漏问题。
实现过程:将malloc和free封装起来,建链表。当调用SV_MALLOC时,向链表中插入一个结点,为结点分配内存,结点存储信息包括为该变量分配内存时所在函数名function,所在行数line,分配的字节大小size以及地址ptr。当调用SV_FREE时,从链表中找到先前malloc的指针变量,将该结点信息从链表中删除并释放该结点的内存空间。
涉及知识:结构体,指针,链表,动态分配内存,封装函数的宏定义小技巧。

先放上代码,抽空再讲吧

#ifndef _TEST_MEM_H_
#define _TEST_MEM_H_

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

/* 用于输出链表的函数 */
void display();

void *sv_malloc(size_t size, char *function, int line);
void sv_free(void *ptr, char *function, int line);

void mem_check_init();

#define SV_MALLOC(size) sv_malloc((size), __FUNCTION__, __LINE__)
#define SV_FREE(ptr)    sv_free(ptr, __FUNCTION__, __LINE__);


#endif 

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

//定义结构体变量类型Elem
typedef struct
{
   
   
	char *function;
	int line;
	int size;
	char *ptr;

}Elem;

//链表中结点的结构
typedef struct Link
{
   
   
	Elem elem;
	struct Link *next;
}link;

//定义未释放内存链表头节点
link *link_list = NULL;

Elem *mem_in;

int mem_in_id;

/**< 初始化链表的函数 */
link * initLink();


/**< p为原链表,elem表示新数据元素,insert_position_number表示新元素要插入的位置 */
link * insertElem(link *p, Elem elem, int insert_position_number);

/**< 删除结点的函数,p代表操作链表,insert_position_number代表删除节点的位置 */
link * deleteElem(link *p, int insert_position_number);

/**< 查找结点的函数,elem为目标结点的数据域的值,查找到元素并删除 */
int selectElemAndDelete(link 
### C/C++ 中结构体链表的动态内存分配 #### 使用 `malloc` 和 `free` 进行动态内存管理 在C/C++中,可以利用标准库函数`malloc()`来为结构体链表节点分配内存,并通过`free()`释放不再使用的内存。这有助于提高程序效率并防止内存泄漏。 对于结构体链表而言,通常会先定义一个表示单个节点的数据结构,该结构不仅包含所需存储的信息字段,还应有一个指向下一个节点的指针成员以便链接各个节点形成列表[^1]。 ```c // 定义链表节点结构 struct Node { int data; struct Node* next; }; ``` 当需要新增加一个元素到链表里时,则调用`malloc()`获取足够的连续字节数作为新结点占用的空间;而删除某个特定位置上的项之前要记得先保存好其后续部分的位置再执行解绑操作最后才是真正意义上的回收工作即调用`free()`函数传入待销毁对象地址参数完成清理任务[^3]。 下面给出一段完整的代码示例展示如何实现上述过程: ```c #include <stdio.h> #include <stdlib.h> // 定义链表节点结构 struct Node { int data; struct Node* next; }; void insertNode(struct Node** head, int newData) { // 创建一个新的节点 struct Node* newNode = (struct Node*)malloc(sizeof(struct Node)); (*newNode).data = newData; (*newNode).next = *head; // 更新头指针指向新的节点 *head = newNode; } void deleteNode(struct Node **head_ref, int key) { // 如果链表为空则直接返回 if (*head_ref == NULL){ return; } // 当第一个节点就是要删除的情况处理 struct Node* temp = *head_ref; if ((*temp).data == key) { *head_ref = temp->next; // 修改头指针 free(temp); // 释放旧头部所占空间 return; } // 查找要删除的关键字所在节点及其前驱节点 struct Node* prev = NULL; while ((temp != NULL) && ((*temp).data != key)) { prev = temp; temp = (*temp).next; } // 若未找到对应关键字则退出 if (temp == NULL) return; // 断开连接并释放目标节点 (*prev).next = (*temp).next; free(temp); } void printList(const struct Node *node) { while(node != NULL) { printf(" %d ", node->data); node = node->next; } } ``` 此段代码实现了基本的功能:向链表前端插入数值以及按照指定值查找并移除匹配项。值得注意的是,在每次成功创建或移除了某节点之后都进行了必要的错误检查以确保不会发生非法访问等问题[^2]。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值