Memory leaks Ada.Strings.Unbounded中的内存泄漏?

Memory leaks Ada.Strings.Unbounded中的内存泄漏?,memory-leaks,valgrind,ada,Memory Leaks,Valgrind,Ada,我有一个奇怪的内存泄漏,似乎库函数到\u无界\u字符串正在泄漏 代码片段: procedure Parse (Str : in String; 。。。做些事情 declare New_Element : constant Ada.Strings.Unbounded.Unbounded_String := Ada.Strings.Unbounded.To_Unbounded_String (Str); -- this leaks begin valgrind输出:

我有一个奇怪的内存泄漏,似乎库函数到\u无界\u字符串正在泄漏

代码片段:

procedure Parse (Str    : in     String;
。。。做些事情

declare
   New_Element : constant Ada.Strings.Unbounded.Unbounded_String :=
     Ada.Strings.Unbounded.To_Unbounded_String (Str); -- this leaks
begin
valgrind输出:

==6009== 10,276 bytes in 1 blocks are possibly lost in loss record 153 of 153
==6009==    at 0x4025BD3: malloc (vg_replace_malloc.c:236)
==6009==    by 0x42703B8: __gnat_malloc (in /usr/lib/libgnat-4.4.so.1)
==6009==    by 0x4269480: system__secondary_stack__ss_allocate (in /usr/lib/libgnat-4.4.so.1)
==6009==    by 0x414929B: ada__strings__unbounded__to_unbounded_string (in /usr/lib/libgnat-4.4.so.1)
==6009==    by 0x80F8AD4: syntax__parser__dash_parser__parseXn (token_parser_g.adb:35)
其中,token_parser_g.adb:35在上面列为“-this leaks”行

其他信息:Gnatmake版本4.4.5。gcc版本4.4 valgrind版本valgrind-3.6.0.SVN-Debian,valgrind选项-v--泄漏检查=完整--读取var信息=是--显示可访问=否

感谢任何帮助或见解


NWS.

Valgrind明确表示,可能存在内存泄漏。这并不一定意味着有一个。例如,如果对该函数的第一次调用分配了一个内存池,该内存池在程序生命周期内重复使用,但从未释放,Valgrind将报告它为可能的内存泄漏,即使它不是,因为这是一种常见做法,并且在进程终止时内存将返回操作系统

现在,如果您认为确实存在内存泄漏,请在循环中调用此函数,然后看到内存继续增长。如果确实如此,请提交一份bug报告,甚至更好,尝试查找并修复漏洞,并随bug报告一起发送补丁


希望有帮助。

试图将此保留在评论中,但我说的太长,开始需要格式化

在Ada中,通常假定字符串对象的大小是完美的。该语言提供函数来返回任何字符串的大小和边界。正因为如此,Ada中的字符串处理与C非常不同,实际上更类似于在Lisp这样的函数式语言中的处理方式

但基本原则是,除了在一些非常不寻常的情况下,如果您发现自己使用的是
Ada.Strings.Unbounded
,那么您将以错误的方式进行操作

使用可变长度字符串(或者可能是带有单独有效_长度变量的缓冲区)确实无法绕过的一种情况是,当从外部源读取字符串作为输入时。正如您所说,您的解析示例就是这样一种情况

然而,即使在这里,您也应该只在初始缓冲区中有这种情况。对解析例程的调用应如下所示:

Ada.Text_IO.Get_Line (Buffer, Buffer_Len);
Parse (Buffer(Buffer'first..Buffer'first + Buffer_Len - 1));
现在,在解析例程中,您可以使用一个大小完美的常量Ada字符串。如果出于某种原因需要拉出子片,则应执行以下操作:

... --// Code to find start and end indices of my subslice
New_Element : constant String := Str(Element_Start...Element_End);
但是,如果出于某种原因,您实际上不需要复制该数据,那么最好只查找
Element\u Start
Element\u End
并使用原始字符串缓冲区的一部分。例如:

if Str(Element_Start..Element_End) = "MyToken" then
我知道这并不能回答你关于Ada.Strings.Unbounded可能泄漏的问题。但是,即使它没有泄漏,该代码也相对浪费了机器资源(CPU和内存),并且可能不应该用于字符串操作,除非您确实需要它

绑定的[ed]字符串是否有作用域

扩展@T.E.D.“对象不应该通过隐式指针和动态分配来实现。”相反,当泛型被实例化时,最大大小是固定的。作为实现细节,GNAT使用指定字符串的最大大小,并使用记录存储当前大小和内容


相反,要求“在分配或范围退出时,与
无界_字符串
对象关联的存储不会丢失。”作为实现细节,GNAT使用从导出的缓冲实现。因此,
无界_字符串所使用的内存在对象最终确定之前可能会出现泄漏,例如当代码返回到封闭范围时。

来自Valgrind手册:“您应该尝试确保您的程序在退出时没有任何明确丢失或可能丢失的块。”因此,直到进一步通知,我会认为它是一个漏洞,虽然你的注意,如果它是真正的增长可能值得调查。谢谢NWS。@NWS:长话短说。从技术上讲,这是一个内存泄漏,但如果你脚踏实地,专注于真正重要的事情,那就不是了,即使Valgrind开发人员不这么认为。但在任何一种情况下都必须报告,因为这可能是一次真正的泄漏,我们正在进行报告。所以,如果您怀疑它是真正的泄漏,那么就调试它。即使valgrind也没有水晶球;)@Vlad-正确,重复调用时它不会增长:)如果我不得不猜测一下,我会说您正在使用的无界_字符串工具正在进行某种惰性的释放,以防止大量不必要的工作(例如:如果您在循环中有您的declare块或
Parse
例程)。因为您使用的是Gnat,所以您可以检查源代码以确定是否使用了.Off-topic,但我认为您很有可能根本不需要在此处使用
Unbounded_String
s。Ada进行字符串操作的方法是创造性地使用作用域和函数,在需要时和需要时构建大小完美的常量字符串。在执行文本I/O输入时,您需要动态大小字符串的唯一时间是缓冲区。@T.E.D.我正是这样做的-解析动态大小的文本输入,即。如果可能的话,我更喜欢使用精确的字符串:)您能提供一个小的可编译源代码来产生错误吗?我想不出一个,这里没有漏洞。(GNAT Pro 6.3.1,valgrind-3.3.1,--读取var info无有效参数)@oenone简言之,无。使用此方法的所有“短程序”均不会产生错误泄漏。只有当内存占用空间较大时才会发生这种情况。(我没有发布8k+行代码!)这也让我得出结论,Vlad很可能是对的,它并不是真正的泄漏。有趣。我根本不知道Ada,但考虑到两者都分配内存等因素,动态字符串处理怎么可能使用比带边界的字符串更多的东西呢。。不管怎样,一天结束时是C。“没有?”特德,我正在考虑使用非无界字符串,