当内存被释放时,Ada 会发生什么?
What happens in Ada when memory is deallocated?
我对 Ada 完全陌生,我必须学习它才能参加学校的课程。
我做过的其中一个练习要求一个过程来交换指针的地址,然后将指针的地址更改为另一个指针的地址,并释放之前的地址。
正如您在下一个示例中所看到的,我正在执行所需的操作,但我很想知道当该地址被释放时发生了什么,通过持有对它的引用,并意识到它会放入垃圾在其中,我猜测该地址的标志已更改,并且某些东西告诉编译器该内存地址已被释放,我只是不确定也无法在网上找到表明我的假设正确与否的东西。
procedure Main is
type T_Pointer is access Integer;
I, J, aux: T_Pointer;
procedure FreeMemoryAddress is new Unchecked_Deallocation(integer, T_Pointer);
procedure ChangePointerAddress(Origen: in out T_Pointer; destino: in T_Pointer);
procedure ChangePointerAddress(Origen: in out T_Pointer; destino: in T_Pointer)
is
begin
origen:=destino;
end ChangePointerAddress;
procedure SwapPointers (I, J: in out T_Pointer);
procedure SwapPointers (I, J: in out T_Pointer)
is
aux: T_Pointer;
begin
aux := new Integer;
Aux := I;
I:=J;
J:=Aux;
end SwapPointers;
begin
I:=new Integer;
J:=new Integer;
Put_Line("i's uninitialized value: " & integer'Image(I.all));
Put_Line("i's address: " & System.Address_Image(I.all'Address));
Put_Line("j's address: " & System.Address_Image(j.all'Address));
SwapPointers(I, J);
Put_Line("After swapping:");
Put_Line("i's address: " & System.Address_Image(I.all'Address));
Put_Line("j's address: " & System.Address_Image(j.all'Address));
aux:=j;
FreeMemoryAddress(j);
Put_Line("aux's value: " & Integer'Image(aux.all)); --garbage
Put_Line("aux's address: " & System.Address_Image(aux.all'Address));
end Main;
看到 I.all
的初始值为 0,我有点惊讶,因为编译器不需要确保分配的内存已初始化(至少,ARM 2012 4.8(9) says "any implicit initial value is assigned", see ARM 3.3.1(10), none 这里就是这种情况)。 VxWorks 5.3 的 GNAT 过去不初始化分配的数据,这让那些在 Windows 上开发的人转向 VxWorks 目标时感到惊讶;我们制作了我们自己的内存分配器版本 (s-memory.adb
),它用 16#deadbeef#
.
填充了内存
我们的分配器还使用类似但不同的模式填充已释放的内存(16#feebdaed#
?-这是前一段时间)。
在 macOS 上,可能在这种情况下,GNAT 内存释放器调用 C free()
,它会做任何它做的事情。返回的内存可能会作为 re-linking 的一部分被覆盖到系统内存区域,and/or 立即重新使用,例如通过您的 post-Free
代码。
概述了 Ada 中内存管理的一些方面 . In the particular case of Unchecked_Deallocation
, the standard advises that an instance "should actually reclaim the storage." As @Simon Wright , the deallocation details may be implementation specific—marking, zeroing or poisoning freed memory—depending on the host operating system. MacOS, for example,使用了几种这样的 security-related 策略;你可能想研究一下你的 OS.
在下面的变体中,我添加了一个 Default_Value
方面和代码来显示 J
被释放前后的值。在调用后尝试引用 J.all
的值,以查看尝试取消引用 null
.
引发的错误
Before Free (J):
J value: -1
J address: 000060000085C030
After Free (J):
J value: 756334640
J address: 000060000085C030
代码:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Unchecked_Deallocation; use Ada;
with System.Address_Image; use System;
procedure Main is
type Int is new Integer with Default_Value => -1;
type Int_Ptr is access Int;
I, J, Temp : Int_Ptr;
procedure Free is new Unchecked_Deallocation (Int, Int_Ptr);
procedure SwapPointers (I, J : in out Int_Ptr) is
Aux : Int_Ptr := new Int;
begin
Aux := I;
I := J;
J := Aux;
end SwapPointers;
begin
I := new Int;
J := new Int;
Put_Line ("I & J values: " & Int'Image (I.all) & " " & Int'Image (J.all));
Put_Line ("I address: " & Address_Image (I.all'Address));
Put_Line ("J address: " & Address_Image (J.all'Address));
SwapPointers (I, J);
Put_Line ("After swapping:");
Put_Line ("I address: " & Address_Image (I.all'Address));
Put_Line ("J address: " & Address_Image (J.all'Address));
Put_Line ("Before Free (J):");
Put_Line ("J value: " & Int'Image (J.all));
Put_Line ("J address: " & Address_Image (J.all'Address));
Temp := J;
Free (J);
Put_Line ("After Free (J):");
Put_Line ("J value: " & Int'Image (Temp.all)); --garbage
Put_Line ("J address: " & Address_Image (Temp.all'Address));
end Main;
我对 Ada 完全陌生,我必须学习它才能参加学校的课程。
我做过的其中一个练习要求一个过程来交换指针的地址,然后将指针的地址更改为另一个指针的地址,并释放之前的地址。
正如您在下一个示例中所看到的,我正在执行所需的操作,但我很想知道当该地址被释放时发生了什么,通过持有对它的引用,并意识到它会放入垃圾在其中,我猜测该地址的标志已更改,并且某些东西告诉编译器该内存地址已被释放,我只是不确定也无法在网上找到表明我的假设正确与否的东西。
procedure Main is
type T_Pointer is access Integer;
I, J, aux: T_Pointer;
procedure FreeMemoryAddress is new Unchecked_Deallocation(integer, T_Pointer);
procedure ChangePointerAddress(Origen: in out T_Pointer; destino: in T_Pointer);
procedure ChangePointerAddress(Origen: in out T_Pointer; destino: in T_Pointer)
is
begin
origen:=destino;
end ChangePointerAddress;
procedure SwapPointers (I, J: in out T_Pointer);
procedure SwapPointers (I, J: in out T_Pointer)
is
aux: T_Pointer;
begin
aux := new Integer;
Aux := I;
I:=J;
J:=Aux;
end SwapPointers;
begin
I:=new Integer;
J:=new Integer;
Put_Line("i's uninitialized value: " & integer'Image(I.all));
Put_Line("i's address: " & System.Address_Image(I.all'Address));
Put_Line("j's address: " & System.Address_Image(j.all'Address));
SwapPointers(I, J);
Put_Line("After swapping:");
Put_Line("i's address: " & System.Address_Image(I.all'Address));
Put_Line("j's address: " & System.Address_Image(j.all'Address));
aux:=j;
FreeMemoryAddress(j);
Put_Line("aux's value: " & Integer'Image(aux.all)); --garbage
Put_Line("aux's address: " & System.Address_Image(aux.all'Address));
end Main;
看到 I.all
的初始值为 0,我有点惊讶,因为编译器不需要确保分配的内存已初始化(至少,ARM 2012 4.8(9) says "any implicit initial value is assigned", see ARM 3.3.1(10), none 这里就是这种情况)。 VxWorks 5.3 的 GNAT 过去不初始化分配的数据,这让那些在 Windows 上开发的人转向 VxWorks 目标时感到惊讶;我们制作了我们自己的内存分配器版本 (s-memory.adb
),它用 16#deadbeef#
.
我们的分配器还使用类似但不同的模式填充已释放的内存(16#feebdaed#
?-这是前一段时间)。
在 macOS 上,可能在这种情况下,GNAT 内存释放器调用 C free()
,它会做任何它做的事情。返回的内存可能会作为 re-linking 的一部分被覆盖到系统内存区域,and/or 立即重新使用,例如通过您的 post-Free
代码。
概述了 Ada 中内存管理的一些方面 Unchecked_Deallocation
, the standard advises that an instance "should actually reclaim the storage." As @Simon Wright
在下面的变体中,我添加了一个 Default_Value
方面和代码来显示 J
被释放前后的值。在调用后尝试引用 J.all
的值,以查看尝试取消引用 null
.
Before Free (J):
J value: -1
J address: 000060000085C030
After Free (J):
J value: 756334640
J address: 000060000085C030
代码:
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Unchecked_Deallocation; use Ada;
with System.Address_Image; use System;
procedure Main is
type Int is new Integer with Default_Value => -1;
type Int_Ptr is access Int;
I, J, Temp : Int_Ptr;
procedure Free is new Unchecked_Deallocation (Int, Int_Ptr);
procedure SwapPointers (I, J : in out Int_Ptr) is
Aux : Int_Ptr := new Int;
begin
Aux := I;
I := J;
J := Aux;
end SwapPointers;
begin
I := new Int;
J := new Int;
Put_Line ("I & J values: " & Int'Image (I.all) & " " & Int'Image (J.all));
Put_Line ("I address: " & Address_Image (I.all'Address));
Put_Line ("J address: " & Address_Image (J.all'Address));
SwapPointers (I, J);
Put_Line ("After swapping:");
Put_Line ("I address: " & Address_Image (I.all'Address));
Put_Line ("J address: " & Address_Image (J.all'Address));
Put_Line ("Before Free (J):");
Put_Line ("J value: " & Int'Image (J.all));
Put_Line ("J address: " & Address_Image (J.all'Address));
Temp := J;
Free (J);
Put_Line ("After Free (J):");
Put_Line ("J value: " & Int'Image (Temp.all)); --garbage
Put_Line ("J address: " & Address_Image (Temp.all'Address));
end Main;