简体   繁体   English

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

[英]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函数:

  1. 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端的字符串释放内存,这样可以吗?

  2. Is it safe if I free the memory from C side? 如果我从C端释放内存,这样安全吗?

  3. 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方面释放这个字符串:

  • the Ada API foresees this, so it's safe Ada API预见​​到了这一点,所以它是安全的
  • the Ada API doesn't give any assurance that the memory is allocated using the C standard library (see package reference ) Ada API不保证使用C标准库分配内存(请参阅包参考
  • you don't know if the internals of the Ada implementation that you use makes use of the standard C library, or if it has its own memory management. 您不知道您使用的Ada实现的内部是否使用标准C库,或者它是否有自己的内存管理。 So it would be extremely risky to free it on the C side, because freeing a pointer that was not allocated with malloc/calloc is undefined behavior. 因此,在C端释放它是非常危险的,因为释放未使用malloc / calloc分配的指针是未定义的行为。

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端留下悬空指针,你可以将字符串作为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;

(spec to be changed to match, of course). (当然,规格要改为匹配)。

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

相关问题 如何将在 C 中分配的字符串返回给 Ada 并在 Ada 中释放它? - How can I return a string allocated in C to Ada and free it in Ada? 释放为C中的字符串分配的内存 - Freeing memory allocated for string in C C - 释放功能中分配的内存 - C - freeing memory allocated in function C-使用带有**参数的函数释放结构的已分配内存 - C - Freeing the allocated memory of the struct using a function with ** parameter 释放结构指针还会释放C中分配给结构内部的内存吗? - Will freeing a structure pointer also free the memory allocated inside of the structure in C? 有没有另一种方法可以在C中释放动态分配的内存 - 不使用free()函数? - Is there an alternative way to free dynamically allocated memory in C - not using the free() function? free()之后分配的内存不释放 - Allocated memory not freeing after free() C function 用于在循环中将字符串数组组合成单个字符串并在释放分配的字符串后返回字符串 memory - C function for combining an array of strings into a single string in a loop and return the string after freeing the allocated memory 释放分配给C中非常长的字符串(char *)的内存? - Freeing up memory allocated for a very long string (char*) in C? c - 为从函数返回的变量释放动态分配的内存 - c - freeing dynamically allocated memory for a variable that is rerturned from a function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM