运行截图:

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

     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. iOS单例创建的一点疑惑

    线程安全的单例常用写法, +(AccountManager *)sharedManager{ static AccountManager *defaultManager = nil; disptch_ ...

  2. 51Nod 独木舟(贪心)

    n个人,已知每个人体重.独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人.显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟? Input 第一行包含 ...

  3. python的模块导入机制

    在python中用import或者from...import来导入相应的模块. 模块(Module)其实就是一些函数和类的集合文件,它能实现一些相应的功能,当我们需要使用这些功能的时候,直接把相应的模 ...

  4. 从Chrome源码看audio/video流媒体实现二(转)

    第一篇主要介绍了Chrome加载音视频的缓冲控制机制和编解码基础,本篇将比较深入地介绍解码播放的过程.以Chromium 69版本做研究. 由于Chromium默认不能播放Mp4,所以需要需要改一下源 ...

  5. ES6学习笔记(十三)Iterator遍历器和for...of循环

    1.概念 遍历器(Iterator)就是这样一种机制.它是一种接口,为各种不同的数据结构提供统一的访问机制.任何数据结构只要部署 Iterator 接口,就可以完成遍历操作(即依次处理该数据结构的所有 ...

  6. 学习优化《机器学习与优化》中文PDF+英文PDF

    正在学习机器学习中的优化处理,感觉<机器学习与优化>写得还是比较通俗易懂的,第七章特征选择我需要,特征提取:相关系数,相关比,熵和互信息..更高级的应该是文本挖掘的特征提取,比如LDA提取 ...

  7. 关于FAT32分区的U盘4GB文件的测试

    关于FAT32分区的U盘4GB文件的测试 很多人都知道FAT32的分区,单文件大小不能超过4GB,关于这个问题就来测测看. FAT32最大文件大小为2的32次方,也就是4294967296 Byte, ...

  8. 【SRM 717 div2 A】 NiceTable

    Problem Statement You are given a vector t that describes a rectangular table of zeroes and ones. Ea ...

  9. [React] Implement a React Context Provider

    If you have state that needs to exist throughout your application, then you may find yourself passin ...

  10. POJ1833 &amp; POJ3187 &amp; POJ3785 next_permutation应用

    要是没有next_permutation这个函数,这些题认为还不算特别水,只是也不一定,那样可能就会有对应的模板了. 反正正是由于next_permutation这个函数.这些题包含之前的POJ122 ...