繁体   English   中英

使用free()释放C函数中的字符串(在Ada中分配)

[英]Freeing a string (allocated in Ada) in a C function using free()

我正在开发一个C-Ada绑定应用程序,我在其中使用Interfaces.C.Strings.New_String()在Ada端分配一个新字符串。

Interfaces.C.Strings已经有一个过程Free()来释放字符串的内存。 因为我需要使用Interfaces.C.Strings.Chars_Ptr将此字符串传递给C函数:

  1. 如果我使用free()函数(在stdlib.h中声明free()为C端的字符串释放内存,这样可以吗?

  2. 如果我从C端释放内存,这样安全吗?

  3. 或者我应该使用Ada方面的Interfaces.C.Strings.Free()函数更好地释放它?

你应该在Ada方面释放这个字符串:

  • Ada API预见​​到了这一点,所以它是安全的
  • Ada API不保证使用C标准库分配内存(请参阅包参考
  • 您不知道您使用的Ada实现的内部是否使用标准C库,或者它是否有自己的内存管理。 因此,在C端释放它是非常危险的,因为释放未使用malloc / calloc分配的指针是未定义的行为。

从C端调用Interfaces.C.Strings.Free有两个问题。

第一个是程序有Convention Ada ,所以你不能确定如何从C调用它,即使你的编译器是GNAT因此基于GCC; 如果不编辑和重建标准库,则无法更改此项。

第二是它的声明是

procedure Free (Item : in out chars_ptr);

这意味着Item通过引用传递( char **item ),以便它可以被清零。

您可以安排C方通过包装调用Ada解除分配。 我的看法是,艾达语义(后Free (Item)Item设置为Null_Ptr )应该被保留,这意味着消费Ç程序被调用需要采取in out参数,译为char **

with Interfaces.C.Strings;
package String_Freeing is

   procedure C_Consumer (Item : in out Interfaces.C.Strings.chars_ptr)
   with
     Import,
     Convention => C,
     External_Name => "c_consumer";

   procedure Free_Wrapper (Item : in out Interfaces.C.Strings.chars_ptr)
   with
     Export,
     Convention => C,
     External_Name => "free_ada_string";

end String_Freeing;

Free_Wrapper必须在要导出的包中),带有正文

package body String_Freeing is
   procedure Free_Wrapper (Item : in out Interfaces.C.Strings.chars_ptr) is
   begin
      Interfaces.C.Strings.Free (Item);
   end Free_Wrapper;
end String_Freeing;

和测试程序

with Interfaces.C.Strings;
with String_Freeing; use String_Freeing;
procedure Test_String_Freeing is
   Str : Interfaces.C.Strings.chars_ptr;
   use type Interfaces.C.Strings.chars_ptr;
begin
   Str := Interfaces.C.Strings.New_String ("hello world.");
   C_Consumer (Str);
   pragma Assert (Str = Interfaces.C.Strings.Null_Ptr, "str not nulled");
end Test_String_Freeing;

事物的C面可能是哪里

#include <stdio.h>

extern void free_ada_string(char **item);

void c_consumer(char **item) {
  printf("%s\n", *item);
  free_ada_string(item);
}

如果你愿意在Ada端留下悬空指针,你可以将字符串作为inchar * )参数传递,这将使Free_Wrapper看起来像

package body String_Freeing is
   procedure Free_Wrapper (Item : Interfaces.C.Strings.chars_ptr) is
      Dummy : Interfaces.C.Strings.chars_ptr := Item;
   begin
      Interfaces.C.Strings.Free (Dummy);
   end Free_Wrapper;
end String_Freeing;

(当然,规格要改为匹配)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM