[英]Freeing a string (allocated in Ada) in a C function using free()
I am working on a C-Ada binding application, where I am allocating a new string in Ada side using Interfaces.C.Strings.New_String()
. 我正在开发一个C-Ada绑定应用程序,我在其中使用
Interfaces.C.Strings.New_String()
在Ada端分配一个新字符串。
Interfaces.C.Strings
already has a procedure Free()
to deallocate the memory for string. Interfaces.C.Strings
已经有一个过程Free()
来释放字符串的内存。 Since I need to pass this string to a C function using Interfaces.C.Strings.Chars_Ptr
: 因为我需要使用
Interfaces.C.Strings.Chars_Ptr
将此字符串传递给C函数:
Is it OK if I deallocate memory for the string in C side using the free()
function (declared in stdlib.h)? 如果我使用
free()
函数(在stdlib.h中声明free()
为C端的字符串释放内存,这样可以吗?
Is it safe if I free the memory from C side? 如果我从C端释放内存,这样安全吗?
Or I should better free it using the Interfaces.C.Strings.Free()
function from Ada side? 或者我应该使用Ada方面的
Interfaces.C.Strings.Free()
函数更好地释放它?
You shall free this string on the Ada side: 你应该在Ada方面释放这个字符串:
There are two problems with calling Interfaces.C.Strings.Free
from the C side. 从C端调用
Interfaces.C.Strings.Free
有两个问题。
The first is that the procedure has Convention Ada
, so you can't be sure of how to call it from C, even if your compiler is GNAT & therefore GCC-based; 第一个是程序有
Convention Ada
,所以你不能确定如何从C调用它,即使你的编译器是GNAT因此基于GCC; and you can't change this without editing and rebuilding the standard library. 如果不编辑和重建标准库,则无法更改此项。
The second is that its declaration is 第二是它的声明是
procedure Free (Item : in out chars_ptr);
which means that Item
is passed by reference ( char **item
) so that it can be nulled. 这意味着
Item
通过引用传递( char **item
),以便它可以被清零。
You could arrange for the C side to call the Ada deallocation with wrapping. 您可以安排C方通过包装调用Ada解除分配。 My view is that the Ada semantics (after
Free (Item)
, Item
is set to Null_Ptr
) should be preserved, which means that the consuming C procedure to be called needs to take an in out
parameter, translated as char **
. 我的看法是,艾达语义(后
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
has to be in a package to be exported), with body (
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;
and test program 和测试程序
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;
where the C side of things might be 事物的C面可能是哪里
#include <stdio.h>
extern void free_ada_string(char **item);
void c_consumer(char **item) {
printf("%s\n", *item);
free_ada_string(item);
}
If you're willing to leave dangling pointers on the Ada side, you could pass the string as an in
( char *
) parameter, which would make Free_Wrapper
look like 如果你愿意在Ada端留下悬空指针,你可以将字符串作为
in
( char *
)参数传递,这将使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;
(spec to be changed to match, of course). (当然,规格要改为匹配)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.