运行截图:

  • 创建记录分配的内存地址大小和地址的结构体

     struct MEM
    {
    void *p;
    int size;
    };
  • 创建管理内存结构体的链表
     typedef struct LinkNode
    {
    struct MEM *pmem;;//保存指针
    struct LinkNode *pNext;//指向下一个结点
    }node,*PNODE;
  • 设置全局变量
     extern struct LinkNode *phead;
  • 向链表中插入一个内存结构体,便于malloc的时候调用
     PNODE addback(PNODE phead, struct MEM *pmem)
    {
    //开辟一个结点
    PNODE pnew = (PNODE)malloc(sizeof(node));
    pnew->pmem = pmem;
    pnew->pNext = NULL; if (phead == NULL)
    {
    phead = pnew;
    }
    else
    {
    //备份首地址
    PNODE ptemp = phead;
    while (ptemp->pNext != NULL)
    {
    ptemp = ptemp->pNext;
    }
    ptemp->pNext = pnew;
    }
    return phead;
    }
  • 修改一个指定的内存结构体,便于realloc的时候调用
     PNODE change(PNODE phead, void *pfind, struct MEM *pnewmem)
    {
    for (PNODE ptmp = phead; ptmp != NULL; ptmp = ptmp->pNext)
    {
    if (ptmp->pmem->p == pfind)
    {
    ptmp->pmem->p = pnewmem->p;
    ptmp->pmem->size = pnewmem->size;
    return phead;
    }
    }
    return phead;
    }
  • 删除一个内存结构体,便于free的时候调用
     PNODE deletenode(PNODE phead, void *paddr)
    {
    //p2保存p1的前一个地址
    PNODE p1, p2;
    p1 = p2 = NULL;
    //遍历寻找内存地址是paddr的内存结构体
    p1 = phead;
    while (p1 != NULL)
    {
    if (p1->pmem->p == paddr)
    {
    break;
    }
    else
    {
    p2 = p1;
    p1 = p1->pNext;//备份上一个
    }
    } if (p1 != phead)
    {
    p2->pNext = p1->pNext;
    free(p1);
    }
    else
    {
    phead = phead->pNext;
    free(p1);
    } return phead;
    }
  • 查找指定内存的结构体,并返回找到的地址
     PNODE findit(PNODE phead, void *pfind)
    {
    for (PNODE ptmp = phead; ptmp != NULL; ptmp = ptmp->pNext)
    {
    if (ptmp->pmem->p == pfind)
    {
    return ptmp;
    }
    }
    return NULL;
    }
  • 显示内存链表的所有数据
     void getinfo(PNODE phead)
    {
    if (phead == NULL)
    {
    printf("目前一共0个地址在堆上,一共消耗0个字节的内存\n");
    printf("-------------------------------------------------------------------------\n\n");
    return;
    } int i = ;//多少个地址
    int j = ;//多少个字节
    for (PNODE p = phead; p != NULL; p = p->pNext)
    {
    i++;
    j += p->pmem->size;
    printf("内存地址=%p 内存大小=%d\n", p->pmem->p, p->pmem->size);
    }
    printf("目前一共%d个地址在堆上,一共消耗%d个字节的内存\n", i, j);
    printf("-------------------------------------------------------------------------\n\n");
    }
  • 释放链表的所有内存
     PNODE deleteall(PNODE phead)
    {
    printf("释放所有内存\n");
    printf("-------------------------------------------------------------------------\n\n");
    PNODE p1 = NULL;
    PNODE p2 = NULL;
    p1 = phead;
    while (p1 != NULL)
    {
    p2 = p1->pNext;
    free(p1->pmem->p);
    p1->pmem->p = NULL;
    free(p1);
    p1 = p2;
    } return NULL; }
  • mymalloc函数,向链表中插入数据
     void *mymalloc(size_t size)
    {
    void *p = malloc(size);
    printf("分配内存 分配的地址%p 大小%d\n", p, size);
    printf("-------------------------------------------------------------------------\n\n");
    //创建一个结点,并且初始化,出入内存管理链表
    struct MEM *pmem = (struct MEM*)malloc(sizeof(struct MEM));
    pmem->p = p;
    pmem->size = size;
    phead = addback(phead, pmem);
    return p;
    }
  • myfree函数,在链表中删除数据
     void myfree(void *p)
    {
    printf("\n内存地址%p释放\n", p);
    printf("-------------------------------------------------------------------------\n\n");
    PNODE px = findit(phead, p);
    if (px == NULL)
    {
    return;
    }
    else
    {
    phead = deletenode(phead, p);//删除
    free(p);
    }
    }
  • myrealloc在链表中修改一个数据
     void *myrealloc(void *p, size_t size)
    { void *pt = realloc(p, size);
    printf("内存地址%p重新分配到%p,大小%d\n",p, pt,size);
    printf("-------------------------------------------------------------------------\n\n");
    struct MEM mymem;
    mymem.p = pt;
    mymem.size = size;
    phead = change(phead, p, &mymem);
    return pt;
    }

main函数宏定义替换 malloc,free,realloc

#define malloc mymalloc
#define free myfree
#define realloc myrealloc

完整代码:

mem.h

 #include <stdio.h>
#include <stdlib.h> //记录分配的内存地址大小和地址
struct MEM
{
void *p;
int size;
}; typedef struct LinkNode
{
struct MEM *pmem;;//保存指针
struct LinkNode *pNext;//指向下一个结点
}node,*PNODE; extern struct LinkNode *phead; //向链表中插入一个数据
PNODE addback(PNODE phead, struct MEM *pmem);
//修改一个数据
PNODE change(PNODE phead, void *pfind, struct MEM *pnewmem);
//删除一个结点
PNODE deletenode(PNODE phead, void *paddr);
//显示
void showall(PNODE phead);
//查找
PNODE findit(PNODE phead,void *pfind);
//获取内存信息
void getinfo(PNODE phead);
//释放所有内存
PNODE deleteall(PNODE phead); void *mymalloc(size_t size);
void myfree(void *p);
void *myrealloc(void *p, size_t size);

mem.cpp

 #include "mem.h"
struct LinkNode *phead = NULL; //插入一个数据
PNODE addback(PNODE phead, struct MEM *pmem)
{
//开辟一个结点
PNODE pnew = (PNODE)malloc(sizeof(node));
pnew->pmem = pmem;
pnew->pNext = NULL; if (phead == NULL)
{
phead = pnew;
}
else
{
//备份首地址
PNODE ptemp = phead;
while (ptemp->pNext != NULL)
{
ptemp = ptemp->pNext;
}
ptemp->pNext = pnew;
}
return phead;
} //修改一个指定的内存结构体
PNODE change(PNODE phead, void *pfind, struct MEM *pnewmem)
{
for (PNODE ptmp = phead; ptmp != NULL; ptmp = ptmp->pNext)
{
if (ptmp->pmem->p == pfind)
{
ptmp->pmem->p = pnewmem->p;
ptmp->pmem->size = pnewmem->size;
return phead;
}
}
return phead;
} //删除一个结点
PNODE deletenode(PNODE phead, void *paddr)
{
//p2保存p1的前一个地址
PNODE p1, p2;
p1 = p2 = NULL; p1 = phead;
while (p1 != NULL)
{
if (p1->pmem->p == paddr)
{
break;
}
else
{
p2 = p1;
p1 = p1->pNext;//备份上一个
}
} if (p1 != phead)
{
p2->pNext = p1->pNext;
free(p1);
}
else
{
phead = phead->pNext;
free(p1);
} return phead;
} //显示所有数据
void showall(PNODE phead)
{
if (phead == NULL)
{
printf("-------------------------------------------------------------------------\n\n");
return;
}
else
{
printf("内存地址=%p 内存大小=%d\n", phead->pmem->p, phead->pmem->size);
showall(phead->pNext);
}
} //查找
PNODE findit(PNODE phead, void *pfind)
{
for (PNODE ptmp = phead; ptmp != NULL; ptmp = ptmp->pNext)
{
if (ptmp->pmem->p == pfind)
{
return ptmp;
}
}
return NULL;
} //获取信息
void getinfo(PNODE phead)
{
if (phead == NULL)
{
printf("目前一共0个地址在堆上,一共消耗0个字节的内存\n");
printf("-------------------------------------------------------------------------\n\n");
return;
} int i = ;//多少个地址
int j = ;//多少个字节
for (PNODE p = phead; p != NULL; p = p->pNext)
{
i++;
j += p->pmem->size;
printf("内存地址=%p 内存大小=%d\n", p->pmem->p, p->pmem->size);
}
printf("目前一共%d个地址在堆上,一共消耗%d个字节的内存\n", i, j);
printf("-------------------------------------------------------------------------\n\n");
} //释放所有内存
PNODE deleteall(PNODE phead)
{
printf("释放所有内存\n");
printf("-------------------------------------------------------------------------\n\n");
PNODE p1 = NULL;
PNODE p2 = NULL;
p1 = phead;
while (p1 != NULL)
{
p2 = p1->pNext;
free(p1->pmem->p);
p1->pmem->p = NULL;
free(p1);
p1 = p2;
} return NULL; } void *mymalloc(size_t size)
{
void *p = malloc(size);
printf("分配内存 分配的地址%p 大小%d\n", p, size);
printf("-------------------------------------------------------------------------\n\n");
//创建一个结点,并且初始化,出入内存管理链表
struct MEM *pmem = (struct MEM*)malloc(sizeof(struct MEM));
pmem->p = p;
pmem->size = size;
phead = addback(phead, pmem);
return p;
} void myfree(void *p)
{
printf("\n内存地址%p释放\n", p);
printf("-------------------------------------------------------------------------\n\n");
PNODE px = findit(phead, p);
if (px == NULL)
{
return;
}
else
{
phead = deletenode(phead, p);//删除
free(p);
}
} void *myrealloc(void *p, size_t size)
{ void *pt = realloc(p, size);
printf("内存地址%p重新分配到%p,大小%d\n",p, pt,size);
printf("-------------------------------------------------------------------------\n\n");
struct MEM mymem;
mymem.p = pt;
mymem.size = size;
phead = change(phead, p, &mymem);
return pt;
}

main.c

#include "mem.h"

#define malloc mymalloc
#define free myfree
#define realloc myrealloc void main()
{
void *p1 = malloc(**);
void *p2 = malloc( * * );
void *p3 = malloc( * * );
getinfo(phead);
realloc(p1, );
getinfo(phead);
free(p3);
getinfo(phead);
phead = deleteall(phead);
getinfo(phead);
system("pause");
}

18.链表管理内存实现c语言自动释放内存的更多相关文章

  1. C++函数中,两个自动释放内存的动态内存申请类

    最近做一个事情,实现一个流程交互,其中主交互流程函数中,涉及较多的内存申请, 而健康的函数,都是在函数退出前将手动申请不再需要的内存释放掉, 使用很多方法,都避免不了较多的出错分支时,一堆的if fr ...

  2. iOS内存管理系列之二:自动释放与便捷方法

    有时候一个所有者创建一个对象后,会立刻将该对象的指针传递给其它所有者.这时,这个创建者不希望再拥有这个对象,但如果立刻给它发送一个release消息会导致这个对象被立刻释放掉——这样其它所有者还没有来 ...

  3. ARC 没有自动释放内存

    http://www.cnblogs.com/qingche/p/4569833.html 定位了好几天,才发现是打印日志没有即时释放内存,使用intrustment

  4. Linux 查看内存(free)、释放内存(基本操作)

    原文链接:http://blog.51cto.com/11495268/2384147 1.简介 1.1 介绍 很多时候,服务器 负载 很高(执行操作 很慢),很多 原因 造成 这种 现象(内存不足 ...

  5. C语言中的内存相关问题

    内存是用来存储数据与程序的,对我们写程序来说非常重要.所以内存对程序来说几乎是本质需求.越简单的程序需要越少的内存,而越庞大越复杂的程序需要更多的内存. 注意:在嵌入式系统中有ROM和RAM两类内存, ...

  6. How Javascript works (Javascript工作原理) (三) 内存管理及如何处理 4 类常见的内存泄漏问题

    个人总结: 1.两种垃圾回收机制: 1)引用标记算法:如果检测到一个对象没有被引用了,就清除它. ***这种算法不能处理循环引用的情况*** 2)标记—清除算法:从根(全局变量)开始向后代变量检测,任 ...

  7. C语言中动态内存分配的本质是什么?

    摘要:C语言中比较重要的就是指针,它可以用来链表操作,谈到链表,很多时候为此分配内存采用动态分配而不是静态分配. 本文分享自华为云社区<[云驻共创]C语言中动态内存分配的本质>,作者: G ...

  8. [c语言]c语言中的内存分配[转]

    在任何程序设计环境及语言中,内存管理都十分重要.在目前的计算机系统或嵌入式系统中,内存资源仍然是有限的.因此在程序设计中,有效地管理内存资源是程序员首先考虑的问题. 第1节主要介绍内存管理基本概念,重 ...

  9. JavaScript 工作原理之三-内存管理及如何处理 4 类常见的内存泄漏问题(译)

    原文请查阅这里,本文有进行删减,文后增了些经验总结. 本系列持续更新中,Github 地址请查阅这里. 这是 JavaScript 工作原理的第三章. 我们将会讨论日常使用中另一个被开发者越来越忽略的 ...

随机推荐

  1. MySQL格式化日期参数

    MySQL格式化日期参数 %a 缩写星期名 %b 缩写月名 %c 月,数值 %D 带有英文前缀的月中的天 %d 月的天,数值(00-31) %e 月的天,数值(0-31) %f 微秒 %H 小时 (0 ...

  2. CUDA学习笔记(五)

    终于实质分析线程的内容了:按照SIMD的方式,每32个线程称为一个线程束,这些线程都执行同一指令,且每个线程都使用私有寄存器进行这一操作请求. 忽然觉得,做CUDA的程序就像是去北京上班:写MPI之后 ...

  3. Lua,github,nginx

    个人觉得这几种工具都是大学里,至少是前几年未曾出现于课本中或者图书馆中的.而如今确实某些公司赫然出现在招聘需求中的东西. 什么是Lua,为什么要用Lua——做手机游戏而被推广的.Lua原来早在93年就 ...

  4. <Sicily>Greatest Common Divisors

    一.题目描述 A common divisor for two positive numbers is a number which both numbers are divisible by. It ...

  5. vue中Object.defineProperty用法

    function def (obj, key, val, enumerable) { Object.defineProperty(obj, key, { value: val, enumerable: ...

  6. OGG切换步骤

    步骤描述 提前准备好切换方案:以及其他相关人员的配合 切换至容灾数据库: (1)停止前端业务,确认目标端数据已经追平 (2)数据校验,确认数据一致 (3)停止生产库OGG进程(停止后可以直接删除) ( ...

  7. 在 Ubuntu 18.04 LTS 无头服务器上安装 Oracle VirtualBox

    作者: Sk 译者: LCTT qhwdw | 2018-10-12 01:59 本教程将指导你在 Ubuntu 18.04 LTS 无头服务器上,一步一步地安装 Oracle VirtualBox. ...

  8. 记录一次Permission denied解决过程

    热烈推荐:超多IT资源,尽在798资源网 朋友网站碰到一个奇怪的问题,程序所在目录无法进行上传操作. 具体细节是这样的:网站所在目录 /www/web/xiangmua 路径下,/www/web 都可 ...

  9. NodeJS学习笔记 (25)逐行读取-readline(ok)

    模块概览 readline是个非常实用的模块.如名字所示,主要用来实现逐行读取,比如读取用户输入,或者读取文件内容.常见使用场景有下面几种,本文会逐一举例说明. 文件逐行读取:比如说进行日志分析. 自 ...

  10. C++输入流

    输出流基本概念  输出流定义在头文件中.大部分程序都会包含头文件,这个头文件又包含了输入流和输出流头文件.头文件还声明了标准控制台输出流cout.  使用输出流的最简单的方法是使用<<运算 ...