You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复链表集合中Valgrind检测到的内存泄漏问题

问题分析与修复方案

内存泄漏的根本原因

你遇到的内存泄漏非常典型:你的链表集合只实现了节点分配(Ajouter),但没有对应的内存回收机制,而且测试程序在每次循环中重复初始化集合,却从未释放上一次循环中分配的节点内存。

具体来说:

  • 每次Essais循环(共100次),你调用Initialiser(Ensemble),但这个操作只是把Ensemble设为Null,并没有释放之前Ajouter分配的所有节点。
  • 每次测试会添加11个节点(10到20共11个整数),100次测试就产生了1100个节点,这些内存在程序结束时都没有被释放,正好对应Valgrind检测到的1100块丢失内存。

修复步骤

1. 给集合包添加内存销毁过程

首先在Ensembles_Chainage包中实现一个Detruire过程,负责迭代释放链表中所有节点的内存。

修改linked_set.adb(即你的Ensembles_Chainage包体),添加以下过程:

procedure Detruire (Ensemble : in out T_Ensemble) is
    Temp, Suivant : T_Ensemble;
begin
    Temp := Ensemble;
    while Temp /= Null loop
        Suivant := Temp.all.Suivant; -- 先保存下一个节点的引用,避免释放后丢失
        Free(Temp); -- 释放当前节点的内存
        Temp := Suivant;
    end loop;
    Ensemble := Null; -- 将集合重置为空状态
end Detruire;

同时要在包的规范文件(.ads)中声明这个过程,确保外部可以调用:

procedure Detruire (Ensemble : in out T_Ensemble);

2. 在测试程序中调用销毁过程

修改测试程序nombre_moyen_tirages_chainage.adb的循环逻辑,在每次测试循环结束后调用Detruire释放本次测试分配的所有节点内存:

for i in 1..Essais loop
    Initialiser (Ensemble); -- 初始化空集合

    loop
        Get_Random_Number(n_alea); -- 获取随机数
        Moyenne := Moyenne + 1; -- 累加抽取次数

        if not(Est_Present (Ensemble, n_alea)) then
            ajouter (Ensemble, n_alea); -- 将随机数添加到集合
        end if;
        exit when Taille (Ensemble) = Max - Min + 1;
    end loop;

    Detruire(Ensemble); -- 释放本次测试中分配的所有节点内存
end loop;

验证修复效果

重新编译程序后用Valgrind检测,你会看到definitely lost和indirectly lost的内存数值都变为0,内存泄漏问题完全解决。

额外建议

  • 养成Ada中分配即回收的习惯,对于动态分配的内存,一定要提供对应的释放机制,避免资源泄漏。
  • 可以优化Initialiser过程,在初始化前先调用Detruire,这样即使外部忘记手动释放,也能避免内存泄漏。

内容的提问来源于stack exchange,提问作者user11110733

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.14 08:43:39