内存泄露 防止在程序关闭后还有忘记释放的内存

2024-06-18 19:18

本文主要是介绍内存泄露 防止在程序关闭后还有忘记释放的内存,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


主要是解决自己分配的内存忘记释放的问题,自己定义了几个函数取代了malloc,calloc,realloc,free这几个函数,尽量跟原有用法一致。



头文件mypool.h

#ifndef _MYPOOL_H
#define _MYPOOL_H

struct Node
{
struct Node *preNode;//前一个节点
struct Node *nextNode;//后一个节点
void **varAddr;//存储指针变量的地址
int size;
char freed;
};

struct Chain
{
struct Node *first;
struct Node *last;
int size;
};
void InitChain();
struct Node* InitNode(struct Node *pn);
int Push(struct Node *pn);
int RemoveChain(void **id);
int FreeChain();


void* MyMalloc(void **p,int size);
void* MyCalloc(void **p,int nsize,int usize);
void* MyRealloc(void **p,int size);
void MyFree(void **p);
#endif



实现代码:mypool.c



/************************************************************************/

/*这些代码主要是实现对自己分配的内存的管理,主要是为了防止在程序关闭后还有忘记释放的内存;*/

/*这块代码并不涉及对内存区块的分配管理。*/

/* 作者:jackyvan ,Email:jackyyvan@gmail.com */

/************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mypool.h"

static struct Chain chain;//定义一个链表的静态变量


/*初始化链表*/
void InitChain()
{
chain.first=NULL;
chain.last=NULL;
chain.size=0;
}
/*初始化一个链表上的节点*/
struct Node* InitNode(struct Node *pn)
{
pn=malloc(sizeof(struct Node));
if(pn==NULL)
return NULL;
pn->preNode=NULL;
pn->nextNode=NULL;
pn->freed=0;
pn->varAddr=0;
pn->size=0;
return pn;
}
/*加入一个新的内存分配的节点*/
int Push(struct Node *pn)
{
struct Node *last=chain.last;
struct Node *first=chain.first;
if(first==NULL)
{
chain.first=pn;
chain.last=pn;
}
else
{
chain.last->nextNode=pn;
pn->preNode=chain.last;
chain.last=pn;
}
chain.size++;
return 1;
}
/*
从链表中移除一个节点
*/
int RemoveChain(void **id)
{
struct Node *first=chain.first;
struct Node *tp1=NULL,*tp2=NULL;
if(first==NULL)
return 0;
while(first)
{

if((long)first->varAddr==(long)id)
{
tp1=first->preNode;
tp2=first->nextNode;
if(tp1)
{
if(tp2)
{
tp1->nextNode=tp2;
tp2->preNode=tp1;
}
else
{
tp1->nextNode=NULL;
chain.last=tp1;
}
}
else
{
tp2->preNode=NULL;
chain.first=tp2;
}
free(first);
chain.size--;
break;
}
first=first->nextNode;
}
return 1;
}
/*清空链表*/
int FreeChain()
{
struct Node *first=chain.first;
struct Node *tp1=NULL;
while(first)
{
tp1=first->nextNode;
free((void *)*(first->varAddr));
free(first);
first=tp1;
}
chain.first=NULL;
chain.last=NULL;
chain.size=0;
return 1;
}
/*
自定义的malloc,calloc,realloc,free函数
void **p参数 是存储分配内存地址的变量的地址,根据这个地址与分配内存关联,进行管理
*/
void* MyMalloc(void **p,int size)
{
struct Node *pn=NULL;
(*p)=malloc(size);
if(p==NULL)
return NULL;
pn=InitNode(pn);
if(pn==NULL)
return NULL;
pn->varAddr=p;
pn->size=size;
Push(pn);
return (*p);
}
void* MyCalloc(void **p,int nsize,int usize)
{
struct Node *pn=NULL;
(*p)=calloc(nsize,usize);
if(p==NULL)
return NULL;
pn=InitNode(pn);
if(pn==NULL)
return NULL;
pn->varAddr=p;
pn->size=nsize*usize;
Push(pn);
return (*p);
}
void* MyRealloc(void **p,int size)
{
struct Node *pn=NULL;
(*p)=realloc((*p),size);
if(p==NULL)
return NULL;
pn=InitNode(pn);
if(pn==NULL)
return NULL;
pn->varAddr=p;
pn->size=size;
RemoveChain(p);
Push(pn);
return (*p);
}

void MyFree(void **p)
{
if((*p)==NULL)
return;
free((*p));//释放内存
RemoveChain(p);//把相关节点从链表移除
}


int main()
{
char *p=NULL;
char *p2=NULL;
int *p3=NULL;
InitChain();
p=MyCalloc(&p,100,sizeof(char));
strcpy(p,"abcdefgh...");
p2=MyMalloc(&p2,18*sizeof(char));
p3=MyMalloc(&p3,10*sizeof(int));
p3=MyRealloc(&p3,20*sizeof(int));
MyFree(&p2);
FreeChain();
return 0;
}

这篇关于内存泄露 防止在程序关闭后还有忘记释放的内存的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1072879

相关文章

C++对象布局及多态实现探索之内存布局(整理的很多链接)

本文通过观察对象的内存布局,跟踪函数调用的汇编代码。分析了C++对象内存的布局情况,虚函数的执行方式,以及虚继承,等等 文章链接:http://dev.yesky.com/254/2191254.shtml      论C/C++函数间动态内存的传递 (2005-07-30)   当你涉及到C/C++的核心编程的时候,你会无止境地与内存管理打交道。 文章链接:http://dev.yesky

Javascript高级程序设计(第四版)--学习记录之变量、内存

原始值与引用值 原始值:简单的数据即基础数据类型,按值访问。 引用值:由多个值构成的对象即复杂数据类型,按引用访问。 动态属性 对于引用值而言,可以随时添加、修改和删除其属性和方法。 let person = new Object();person.name = 'Jason';person.age = 42;console.log(person.name,person.age);//'J

uniapp接入微信小程序原生代码配置方案(优化版)

uniapp项目需要把微信小程序原生语法的功能代码嵌套过来,无需把原生代码转换为uniapp,可以配置拷贝的方式集成过来 1、拷贝代码包到src目录 2、vue.config.js中配置原生代码包直接拷贝到编译目录中 3、pages.json中配置分包目录,原生入口组件的路径 4、manifest.json中配置分包,使用原生组件 5、需要把原生代码包里的页面修改成组件的方

如何开启和关闭3GB模式

https://jingyan.baidu.com/article/4d58d5414dfc2f9dd4e9c082.html

Java面试八股之怎么通过Java程序判断JVM是32位还是64位

怎么通过Java程序判断JVM是32位还是64位 可以通过Java程序内部检查系统属性来判断当前运行的JVM是32位还是64位。以下是一个简单的方法: public class JvmBitCheck {public static void main(String[] args) {String arch = System.getProperty("os.arch");String dataM

问题-windows-VPN不正确关闭导致网页打不开

为什么会发生这类事情呢? 主要原因是关机之前vpn没有关掉导致的。 至于为什么没关掉vpn会导致网页打不开,我猜测是因为vpn建立的链接没被更改。 正确关掉vpn的时候,会把ip链接断掉,如果你不正确关掉,ip链接没有断掉,此时你vpn又是没启动的,没有域名解析,所以就打不开网站。 你可以在打不开网页的时候,把vpn打开,你会发现网络又可以登录了。 方法一 注意:方法一虽然方便,但是可能会有

一道经典Python程序样例带你飞速掌握Python的字典和列表

Python中的列表(list)和字典(dict)是两种常用的数据结构,它们在数据组织和存储方面有很大的不同。 列表(List) 列表是Python中的一种有序集合,可以随时添加和删除其中的元素。列表中的元素可以是任何数据类型,包括数字、字符串、其他列表等。列表使用方括号[]表示,元素之间用逗号,分隔。 定义和使用 # 定义一个列表 fruits = ['apple', 'banana

Android SurfaceFlinger——图形内存分配器(十一)

前面的文章中的图层合成器(HWC),这里我们接着看一下 SurfaceFlinger 中的另一个重要服务——图形内存分配器。 一、简介         android.hardware.graphics.allocator@2.0 是 Android 系统中硬件抽象层(HAL)的一个组件,专门用于图形内存的分配和管理。它是 SurfaceFlinger 在处理图形数据时所依赖的

美容美发店营销版微信小程序源码

打造线上生意新篇章 一、引言:微信小程序,开启美容美发行业新纪元 在数字化时代,微信小程序以其便捷、高效的特点,成为了美容美发行业营销的新宠。本文将带您深入了解美容美发营销微信小程序,探讨其独特优势及如何助力商家实现业务增长。 二、微信小程序:美容美发行业的得力助手 拓宽客源渠道:微信小程序基于微信社交平台,轻松实现线上线下融合,帮助商家快速吸引潜在客户,拓宽客源渠道。 提升用户体验:

程序人生--拔丝地瓜

一个会享受生活的人,难免会执迷于探索“三餐茶饭,四季衣裳”的朴素涵义。如今在这繁杂喧闹、竞争激烈的社会环境里,如何才能从周而复始的生活中挖掘出一点儿期待!这是一个仁者见仁智者见智的开放性话题。对于大部分的人来说,看电影、运动、旅游、美食、加班....是假日的备选安排。 春节临走之前,再次尝试“拔丝地瓜”,为何要强调“再次”二字?因为这道甜菜我已经尝试过很多次,失败与成功都经历过。十几年的烧饭经历