Ada.Strings.Unbounded内存泄漏?

时间:2011-09-08 21:22:39

标签: memory-leaks valgrind ada

我有一个好奇的内存泄漏,似乎库函数to_unbounded_string正在泄漏!

代码段:

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 --leak-check = full --read-var-info = yes --show-reachable = no

感谢任何帮助或见解,

NWS。

3 个答案:

答案 0 :(得分:4)

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

现在,如果您认为存在真正的内存泄漏,请在循环中调用此函数,并看到内存继续增长。如果确实如此 - 提交错误报告甚至更好,请尝试查找并修复泄漏并发送修补程序以及错误报告。

希望它有所帮助。

答案 1 :(得分:2)

试图保留这些评论,但我所说的太久了,开始需要格式化。

在Ada中,字符串对象通常被认为是完美的大小。该语言提供函数来返回任何字符串的大小和边界。因此,Ada中的字符串处理与C非常不同,实际上更像是在像Lisp这样的函数式语言中使用它。

但基本原则是,除了在一些非常不寻常的情况下,如果你发现自己使用Ada.Strings.Unbounded,你就会采取错误的方式。

使用可变长度字符串(或者可能是具有单独的valid_length变量的缓冲区)实际上无法解决的一种情况是从一些外部源读取字符串作为输入时。正如您所说,您的解析示例就是这种情况。

然而,即使在这里,你应该只在初始缓冲区上有这种情况。你对Parse例程的调用应该是这样的:

Ada.Text_IO.Get_Line (Buffer, Buffer_Len);
Parse (Buffer(Buffer'first..Buffer'first + Buffer_Len - 1));

现在在Parse例程中,你有一个完美大小的常量Ada字符串可供使用。如果由于某种原因你需要拉出一个子片,你会做以下事情:

... --// Code to find start and end indices of my subslice
New_Element : constant String := Str(Element_Start...Element_End);

如果您实际上不需要出于某种原因制作该数据的副本,那么最好只查找Element_StartElement_End并使用原始字符串缓冲区的片段。例如:

if Str(Element_Start..Element_End) = "MyToken" then

我知道这并没有回答你关于Ada.Strings的问题。没有可能泄漏。但即使它没有泄漏,该代码相对浪费机器资源(CPU和内存),并且可能不应该用于字符串操作,除非你真的需要它。

答案 2 :(得分:1)

  

绑定[ed]字符串作用域?

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

相反,Ada.Strings.Unbounded要求“在分配或范围退出时,与Unbounded_String对象关联的存储不会丢失。”作为一个细节,GNAT使用从Ada.Finalization.Controlled派生的缓冲实现。因此,Unbounded_String使用的内存可能出现,直到对象完成为止,例如当代码返回到封闭范围时。