数据结构---双向链表(内存泄露相关知识)

news2024/11/15 16:18:46

一、内存泄露

内存泄露(Memory Leak)是指程序中已动态分配的堆内存由于某种原因程序未释放或无法释放,造成系统内存的浪费,导致程序运行速度减慢甚至系统崩溃等严重后果。内存泄漏是程序设计中常见的错误之一,其特点包括隐蔽性和积累性。

一、内存泄露的定义

       内存泄漏并非指内存在物理上的消失,而是指应用程序分配某段内存后,由于设计错误或疏忽,失去了对该段内存的控制,使得该内存无法被再次使用或回收,从而造成了内存的浪费。

二、内存泄露的原因

1. 资源未被正确释放:程序中动态分配的内存(如使用malloc、new等函数分配的内存)在不再使用时,必须显式地释放(如使用free、delete等函数)。如果忘记释放或者释放时机不当,就会导致内存泄漏。

2. 垃圾回收机制失效:在一些使用垃圾回收机制的语言中(如Java、Python等),如果垃圾回收器未能及时回收无用的内存对象,也可能导致内存泄漏。这通常是由于程序中存在对无用对象的引用,使得垃圾回收器无法识别并回收这些对象。

3. 循环引用:在对象间存在循环引用的情况下,即使这些对象已经不再被程序的其他部分使用,它们也可能因为相互引用而无法被垃圾回收器回收,从而导致内存泄漏。

4. 程序设计错误:如错误的算法设计、错误的内存分配策略等,都可能导致内存泄漏。

 三、内存泄露的影响

内存泄漏会导致系统可用内存逐渐减少,进而影响程序的运行速度和稳定性。在极端情况下,内存泄漏甚至可能导致系统崩溃或无法响应。此外,内存泄漏还可能引发安全问题,如敏感信息泄露等。

四、如何避免内存泄漏

为了避免内存泄漏,开发人员可以采取以下措施:

1. 合理设计程序:在程序设计阶段就考虑到内存管理的问题,采用合适的算法和数据结构来减少内存的使用和泄漏。

2. 及时释放内存:在程序中及时释放不再使用的内存资源,避免内存泄漏的发生。

3. 使用内存检测工具:利用专业的内存检测工具来检测和分析程序中的内存泄漏问题,及时修复潜在的内存泄漏点。如使用valgrind工具

4. 编写高质量的代码:通过代码审查、单元测试等方式来提高代码质量,减少因程序设计错误导致的内存泄漏问题。

二、双向链表

双向链表(Doubly Linked List)是一种数据结构,它与单向链表相似,但每个节点不仅包含指向下一个节点的指针,还包含指向上一个节点的指针。

双向链表的每个节点通常包含以下两个指针:

  • prev:指向上一个节点
  • next:指向下一个节点

通过这两个指针,可以在双向链表中沿着两个方向遍历。

相比于单向链表,双向链表能够更方便地进行插入和删除操作。因为每个节点包含指向前一个节点的指针,所以在删除或插入一个节点时,只需要修改该节点前后节点的指针即可。而在单向链表中,则需要在删除或插入节点时,找到该节点的前一个节点,以便进行指针修改,显得相对麻烦。

//头插
int push_doulink_head(DLink_t *pdoulink, DataType data)
{
    DLink_Node_t *pnode = malloc(sizeof(DLink_Node_t));
    if(NULL == pnode)
    {
        perror("fail malloc");
        return -1;
    }
    pnode->data = data;
    pnode->ppre = NULL;
    pnode->pnext = NULL;
    if(is_empty_doulink(pdoulink))
    {
        pdoulink->phead = pnode;
    }
    else
    {
        pnode->pnext = pdoulink->phead;
        pdoulink->phead->ppre = pnode;
        pdoulink->phead = pnode;
    }
    pdoulink->clen++;
    return 0;
}
//遍历
void push_printlist(DLink_t *pdoulink, int dir)
{
    if(is_empty_doulink(pdoulink))
    {
        return;
    }
    DLink_Node_t *p = pdoulink->phead;
    if(dir)
    {
        while(p != NULL)
        {
            printf("%d ", p->data.id);
            printf("%s ", p->data.name);
            printf("%d \n", p->data.score);
            p = p->pnext;
        }
    }
    else
    {
        while(p->pnext != NULL)
        {
            p = p->pnext;
        }
        while(p != NULL)
        {
            printf("%d ", p->data.id);
            printf("%s ", p->data.name);
            printf("%d \n", p->data.score);
            p = p->ppre;
        }
    }
}
//尾插
int push_doulink_end(DLink_t *pdoulink, DataType data)
{
    if(is_empty_doulink(pdoulink))
    {
        push_doulink_head(pdoulink, data);
    }
    else
    {
    DLink_Node_t *p = pdoulink->phead;
    DLink_Node_t *pnode = malloc(sizeof(DLink_Node_t));
    if(NULL == pnode)
    {
        perror("fail malloc");
        return -1;
    }
    pnode->data = data;
    pnode->ppre = NULL;
    pnode->pnext = NULL;

    while(p->pnext != NULL)
    {
        p = p->pnext;
    }
    p->pnext = pnode;
    pnode->pnext = NULL;
    pnode->ppre = p;
    pdoulink->clen++;
    }
}

 使用头删时,需要注意当只有一个节点的情况,对于双向链表而言,p->pnext为空,此时p->pnext->ppre不存在,无法置为空,会发生栈崩溃。

//头删
int push_doulink_headpop(DLink_t *pdoulink)
{
    if(is_empty_doulink(pdoulink))
    {
        return 0;
    }
    DLink_Node_t *p = pdoulink->phead;
    pdoulink->phead = p->pnext;
    if(p->pnext != NULL)
    {
        p->pnext->ppre = NULL;
    }
    free(p);
    pdoulink->clen--;
    return 1;
}
//尾删
int push_doulink_endpop(DLink_t *pdoulink)
{
    if(is_empty_doulink(pdoulink))
    {
        return 0;
    }
    DLink_Node_t *p = pdoulink->phead;
    if(p->pnext == NULL)
    {
        push_doulink_headpop(pdoulink);
    }
    else
    {
        while(p->pnext != NULL)
        {
            p =p->pnext;
        }
        p->ppre->pnext = NULL;
        free(p);
        pdoulink->clen--;
        return 1;
    }
}

 使用完要及时销毁,避免内存泄露,可使用valgrind ./a.out查看是否发生内存泄露。

//销毁
void destroy_pdoulink(DLink_t *pdoulink)
{
    while(!(is_empty_doulink(pdoulink)))
    {
        push_doulink_headpop(pdoulink);
    }
    free(pdoulink);

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2105935.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C语言学习笔记 Day16(C10文件管理--下)

Day16 内容梳理: C语言学习笔记 Day14(文件管理--上)-CSDN博客 C语言学习笔记 Day15(文件管理--中)-CSDN博客 目录 Chapter 10 文件操作 10.5 文件状态 10.6 文件的随机读写 fseek()、rewind() (1&…

chapter13-常用类——(String类)——day15

目录 466-String结构剖析 467-String结构剖析 468-String测试题1 469-String测试题2 470-String对象特性1 471-String对象特性2 472-String常用方法1 473-String常用方法2 474-String常用方法3 466-String结构剖析 1、接口Serializabel,说明String对象可以串…

智汇云舟受邀参加2024第四届国产水科学数值模型开发创新与技术应用研讨会,并成为“科技智水产业联盟”创始成员

在数字化浪潮的推动下,智慧水利作为国家战略的重要组成部分,正迎来前所未有的发展机遇。8月27-29日,由浙江贵仁信息科技股份有限公司主办、浙江省水利学会协办的“2024第四届国产水科学数值模型开发创新与技术应用研讨会”在杭州白马湖建国饭…

【深度学习】向量化

1. 什么是向量化 向量化通常是消除代码中显示for循环语句的技巧,在深度学习实际应用中,可能会遇到大量的训练数据,因为深度学习算法往往在这种情况下表现更好,所以代码的运行速度非常重要,否则如果它运行在一个大的数据…

英伟达AI超级计算机SuperPod:H100→GH200→GB200

英伟达的 DGX SuperPOD 是一台完整的数据中心级 AI 超级计算机,采用模块化的设计,支持不同规模大小的设计。每台超级计算机都在出厂前完成了搭建、布线和测试,从而大大加快了在用户数据中心的部署速度 。 NVIDIA DGX SuperPOD是下一代数据中心…

【设计模式】单例、工厂、策略、责任链模式

1.单例模式 单例模式确保某个类只有一个实例,主要使用有两种:懒汉式单例、饿汉式单例 单例模式有以下特点:   1、单例类只能有一个实例。   2、单例类必须自己创建自己的唯一实例。   3、单例类必须给所有其他对象提供这一实例。 使用场景: 数据库连接池:单例模式…

Python 算法交易实验87 QTV200日常推进-沪深300的交易量统计

说明 上一篇 讲到,就全市场的交易量来看,近3年也看不出很奇怪的地方;因此,交易量[支持度]不足而导致的策略失灵似乎也说不通。 为了进一步确认,我打算: 1 获取沪深300成分股,只统计成分股的交…

RDD、DataFrame、DataSet(Spark)

RDD、DataFrame、DataSet RDD (弹性分布式数据集): 版本: Spark的初始版本,1.0开始提供。特性: RDD是Spark的基础数据结构,表示一个不可变的分布式对象集合。可以通过转换操作(如map、filter、flatMap)和行动操作&…

outlook设置规则后,规则无法自动运行的解决方案

outlook设置规则后,规则无法自动运行的解决方案 问题描述解决方案说明 问题描述 在outlook设置规则对邮件进行文件夹移动时,有时会出现规则无法自动运行的情况。出现这种情况有很多原因和解决方案,本文列出其中一种。 解决方案 outlook版本…

吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)1.9-1.10

目录 第四门课 卷积神经网络(Convolutional Neural Networks)第一周 卷积神经网络(Foundations of Convolutional Neural Networks)1.9 池化层(Pooling layers)1.10 卷 积 神 经 网 络 示 例 ( …

JDBC的介绍

一 JDBC的简介 1.1 ODBC的出现 早期的数据库应用程序开发,因为没有通用的针对与数据库的编程接口,所以,开发人员需要学习相关数据库的API,才可以进行应用程序,这样增加了学习成本和开发周期。因此整个开发市场一直在呼…

QT creator堆栈窗体demo

创建项目选择QDialog,不要选QMainWindow #ifndef DIALOGSTACK_H #define DIALOGSTACK_H#include <QDialog> #include <QListWidget>//列表框 #include <QStackedWidget>//堆栈窗体 #include <QLabel>QT_BEGIN_NAMESPACE namespace Ui { class DialogSt…

集成电路学习:什么是NOR Flash Memory非易失性闪存存储器

一、NOR Flash Memory&#xff1a;非易失性闪存存储器 NOR Flash Memory&#xff0c;即非易失性闪存存储器的一种&#xff0c;是Flash存储器的一个重要分支。Flash存储器&#xff0c;又称为闪存&#xff0c;结合了ROM&#xff08;只读存储器&#xff09;和RAM&#xff08;随机存…

力扣面试150 分隔链表 模拟

Problem: 86. 分隔链表 &#x1f468;‍&#x1f3eb; 参考题解 Code /*** Definition for singly-linked list.* public class ListNode {* int val;* ListNode next;* ListNode() {}* ListNode(int val) { this.val val; }* ListNode(int val, ListNo…

SQL - SQL优化

在sql查询中为了提高查询效率&#xff0c;我们常常会采取一些措施对查询语句进行sql优化&#xff0c;下面总结的一些方法&#xff0c;有需要的可以参考参考 一、查询SQL尽量不要使用select *&#xff0c;而是具体字段 // 建议 SELECT id,user_name,age,tel FROM user// 不建议…

UEFI BIOS之SMBIOS

SMBIO spec: SMBIOS Specification (dmtf.org) https://www.dmtf.org/sites/default/files/standards/documents/DSP0134_3.5.0.pdf SMBIOS SMBIOS&#xff08;System Management BIOS&#xff09;是一种标准化的系统信息数据结构&#xff0c;旨在提供有关计算机硬件配置、…

Java SPI机制源码

文章目录 SPI简介使用案例SPI的应用SPI机制源码SPI与类加载器双亲委派机制 SPI简介 Java的SPI&#xff08;Service Provider Interface&#xff09;机制允许第三方为应用程序提供插件式的扩展&#xff0c;而不需要修改应用程序本身的代码&#xff0c;从而实现了解耦。Java标准库…

HUAWEI华为MateBook B5-420 i5 集显(KLCZ-WXX9,KLCZ-WDH9)原装出厂Windows10系统文件下载

适用型号&#xff1a;KLCZ-WXX9、KLCZ-WDH9 链接&#xff1a;https://pan.baidu.com/s/12xnaLtcPjZoyfCcJUHynVQ?pwdelul 提取码&#xff1a;elul 华为原装系统自带所有驱动、出厂主题壁纸、系统属性联机支持标志、系统属性专属LOGO标志、华为浏览器、Office办公软件、华为…

[数据集][目标检测]石油泄漏检测数据集VOC+YOLO格式6633张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;6633 标注数量(xml文件个数)&#xff1a;6633 标注数量(txt文件个数)&#xff1a;6633 标注…

网络安全硬件

传统防火墙 传统防火墙 技术&#xff1a;访问控制、代理技术、会话机制 工作层次&#xff1a;应用层一下 防御模式&#xff1a;通过防御设备划分边界&#xff0c;基于IP/端口和特征进行判断&#xff1b;以隔离为基础&#xff0c;基于信任原则构建安全框架&#xff1b;以防护为…