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

使用GNAT.Regpat疑似内存泄漏,求排查及处理方案

关于GNAT.Regpat编译正则表达式后的内存泄漏疑问

我在使用Ada95开发时怀疑存在内存泄漏,用valgrind-3.18.1检测后,发现编译8个正则表达式模式后出现了内存泄漏提示,这些正则是通过GNAT.Regpat实现的。

执行的valgrind命令:

valgrind --leak-check=full --show-leak-kinds=all ./main

检测输出:

==8835== Memcheck, a memory error detector
==8835== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==8835== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==8835== Command: ./main
==8835== 
LT_ASSING
==8835== HEAP SUMMARY:
==8835==     in use at exit: 552 bytes in 8 blocks
==8835==   total heap usage: 12 allocs, 4 frees, 680 bytes allocated
==8835== 
==8835== 28 bytes in 1 blocks are still reachable in loss record 1 of 8
==8835==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==8835==    by 0x41F46E: __gnat_malloc (in /home/mg/Developing/Ada95/SF/obj/main)
==8835==    by 0x405E88: sf_lexer___elabs (in /home/mg/Developing/Ada95/SF/obj/main)
==8835==    by 0x4055B2: adainit (in /home/mg/Developing/Ada95/SF/obj/main)
==8835==    by 0x405651: main (in /home/mg/Developing/Ada95/SF/obj/main)
==8835== 
.
(6 entries practically identical to these two ↑ ↓)
.
==8835== 112 bytes in 1 blocks are still reachable in loss record 8 of 8
==8835==    at 0x4848899: malloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==8835==    by 0x41F46E: __gnat_malloc (in /home/mg/Developing/Ada95/SF/obj/main)
==8835==    by 0x406224: sf_lexer___elabs (in /home/mg/Developing/Ada95/SF/obj/main)
==8835==    by 0x4055B2: adainit (in /home/mg/Developing/Ada95/SF/obj/main)
==8835==    by 0x405651: main (in /home/mg/Developing/Ada95/SF/obj/main)
==8835== 
==8835== LEAK SUMMARY:
==8835==    definitely lost: 0 bytes in 0 blocks
==8835==    indirectly lost: 0 bytes in 0 blocks
==8835==      possibly lost: 0 bytes in 0 blocks
==8835==    still reachable: 552 bytes in 8 blocks
==8835==         suppressed: 0 bytes in 0 blocks
==8835== 
==8835== For lists of detected and suppressed errors, rerun with: -s
==8835== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

这些泄漏对应的是我在sf_lexer.ads中编译的8个正则表达式,代码片段如下:

package RE renames GNAT.Regpat;

Number:    RE.Pattern_Matcher := RE.Compile("[1-9][0-9]*");
Character: RE.Pattern_Matcher := RE.Compile("'.'");
String_t:  RE.Pattern_Matcher := RE.Compile("""([^""]*)""");
Equal:     RE.Pattern_Matcher := RE.Compile("=");
Semicolon: RE.Pattern_Matcher := RE.Compile(";");
Types:     RE.Pattern_Matcher := RE.Compile("^(void|int|char|str)$");
Variable:  RE.Pattern_Matcher := RE.Compile("^[a-zA-Z_][a-zA-Z0-9_]*$");
Keyword:   RE.Pattern_Matcher := RE.Compile("^(if|else|loop|return|int|char|str)$");

请问这确实是GNAT.Regpat的内存泄漏问题吗?我是否需要手动释放编译后的正则表达式占用的内存?


解答

  1. 这不属于真正的内存泄漏
    Valgrind报告的still reachable类型内存,是程序退出时仍有有效指针指向的内存块,并非无法回收的泄漏。Ada运行时会在程序终止时统一回收所有内存,这类内存不会造成长期资源占用问题。

  2. 无需手动释放Pattern_Matcher内存
    GNAT.Regpat的Pattern_Matcher类型内存管理由Ada运行时负责。你定义的是包级全局变量,生命周期和程序一致,程序结束时运行时会自动清理相关资源。

  3. 消除Valgrind提示的可选方案
    如果希望Valgrind不再报告这类内存,可以将正则编译逻辑放到子程序内部使用局部变量,或者调用GNAT.Regpat提供的RE.Free操作。但注意,包级全局变量如果调用Free,可能导致后续使用时出错,因为全局变量的生命周期贯穿整个程序。

另外,still reachable类别的提示通常可以忽略,除非你编写的是长期运行的服务程序需要严格控制内存占用,普通短生命周期程序的这种情况完全正常。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 13:02:17