首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >使用free()释放C函数中的字符串(在Ada中分配)

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

Stack Overflow用户
提问于 2016-03-21 13:59:41
回答 2查看 481关注 0票数 4

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

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

  1. 如果我使用free()函数(在stdlib.h中声明)为C端的字符串释放内存,可以吗?
  2. 如果我把内存从C侧释放出来,安全吗?
  3. 或者我应该使用Ada侧的Interfaces.C.Strings.Free()函数来释放它呢?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-03-21 23:27:14

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

首先,这个过程有Convention Ada,所以您无法确定如何从C调用它,即使您的编译器是GNAT &因此是基于GCC的;如果不编辑和重建标准库,就不能更改它。

第二,它的声明是

代码语言:javascript
运行
复制
procedure Free (Item : in out chars_ptr);

这意味着Item是通过引用(char **item)传递的,因此它可以为空。

您可以安排C端用包装调用Ada解除分配。我的观点是,应该保留Ada语义(在Free (Item)之后,Item设置为Null_Ptr),这意味着要调用的消费C过程需要接受一个in out参数,转换为char **

代码语言:javascript
运行
复制
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必须在要导出的包中)

代码语言:javascript
运行
复制
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;

和测试程序

代码语言:javascript
运行
复制
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面可能在哪里

代码语言:javascript
运行
复制
#include <stdio.h>

extern void free_ada_string(char **item);

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

如果您愿意将悬空指针放在Ada端,则可以将字符串作为in (char *)参数传递,这将使Free_Wrapper看起来像

代码语言:javascript
运行
复制
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;

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

票数 4
EN

Stack Overflow用户

发布于 2016-03-21 14:02:42

您应该释放Ada侧的这条字符串:

  • API预见到了这一点,所以它是安全的
  • Ada没有保证内存是使用C标准库分配的(请参阅包参考)
  • 您不知道您使用的Ada实现的内部是否使用了标准C库,或者它是否有自己的内存管理。因此,在C端释放它是非常危险的,因为释放未用malloc/calloc分配的指针是未定义的行为。
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36133030

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档