使用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的内存泄漏问题吗?我是否需要手动释放编译后的正则表达式占用的内存?
解答
这不属于真正的内存泄漏
Valgrind报告的still reachable类型内存,是程序退出时仍有有效指针指向的内存块,并非无法回收的泄漏。Ada运行时会在程序终止时统一回收所有内存,这类内存不会造成长期资源占用问题。无需手动释放
Pattern_Matcher内存
GNAT.Regpat的Pattern_Matcher类型内存管理由Ada运行时负责。你定义的是包级全局变量,生命周期和程序一致,程序结束时运行时会自动清理相关资源。消除Valgrind提示的可选方案
如果希望Valgrind不再报告这类内存,可以将正则编译逻辑放到子程序内部使用局部变量,或者调用GNAT.Regpat提供的RE.Free操作。但注意,包级全局变量如果调用Free,可能导致后续使用时出错,因为全局变量的生命周期贯穿整个程序。
另外,still reachable类别的提示通常可以忽略,除非你编写的是长期运行的服务程序需要严格控制内存占用,普通短生命周期程序的这种情况完全正常。
内容的提问来源于stack exchange,提问作者Stefano Fattore
相关产品推荐
相关产品推荐

