簡體   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