多态类型函数参数的深拷贝
Deep copy of function arguments for polymorphic types
我使用基于基本包的对象,大致定义为:
package Base is
type T_Base is abstract tagged null record;
-- This performs a deep copy. Shallow copies may lead to STORAGE_ERROR.
-- This shall be implemented by every derived type.
function Copy (From : in T_Base) return T_Base'Class is abstract;
end package Base;
这个包是由几个进一步派生的包派生出来的
package Foo is
type T_Foo is new T_Base with record
A_Data : Natural; -- Of course, in the real code, these are types by far more complex.
end record;
procedure do_something (Foo_Object : in T_Foo);
-- This implements the deep copy
function Copy (From : in T_Foo) return T_Base'Class is abstract;
end package Foo;
在调用过程 do_something
时,我得到了一个 storage_error
:
procedure handle_received_foo (Foo_In: in Foo.T_Foo) is
begin
Foo.do_something (Foo_Object => Foo_In); -- The storage error does happen here.
end main;
当 运行 使用 gdb 的代码时,我在进入函数时遇到段错误,我得到:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 39 (LWP 39)]
0x033c9828 in foo.do_something (foo_object=...) at ./foo.adb:67
67 procedure do_something (Foo_Object : in T_Foo);
(gdb) p foo_object
(null)
所以我想我在做参数 Foo_Object
.
的浅拷贝时得到了 storage_error
我知道这不是 MWE,派生类型中使用的其中一种类型可能存在错误。
我找不到任何好的选择:
使 T_Foo
成为 Controlled
类型以在 Adjust
中调用 Copy
似乎是不可能的,除非我尽可能地大幅改变它的定义' t 从 T_Base
和 Ada.Finalization.Controlled
派生 T_Foo
因为其中 none 是接口类型
定义 T_Base
为
type T_Base is abstract new Ada.Finalization.Controlled with null record;
并覆盖 Adjust
这里似乎对现有代码库进行了大量修改,因为在多个地方产生了 gnat
type of aggregate has private ancestor "Controlled" must use extension aggregate.
所以我没有进一步调查问题或用锤子解决问题的解决方案。
问题不在 Copy
函数中。我在代码库中看到的注释具有误导性。
引入新变量改变异常位置的事实让我考虑了一些堆栈溢出问题。
确实为任务分配的 Storage_Size
是不够的。增加 pragma Storage_Size(<value>)
解决了问题。
由于代码库是用-fstack-check
编译的,这导致了前面提到的STORAGE_ERROR
。
更多信息on Adacore's documentation。
这可能已经在 Gem #95: Dynamic Stack Analysis in GNAT 中看到了,但我目前无法看到其中建议的绑定选项的任何结果。
我使用基于基本包的对象,大致定义为:
package Base is
type T_Base is abstract tagged null record;
-- This performs a deep copy. Shallow copies may lead to STORAGE_ERROR.
-- This shall be implemented by every derived type.
function Copy (From : in T_Base) return T_Base'Class is abstract;
end package Base;
这个包是由几个进一步派生的包派生出来的
package Foo is
type T_Foo is new T_Base with record
A_Data : Natural; -- Of course, in the real code, these are types by far more complex.
end record;
procedure do_something (Foo_Object : in T_Foo);
-- This implements the deep copy
function Copy (From : in T_Foo) return T_Base'Class is abstract;
end package Foo;
在调用过程 do_something
时,我得到了一个 storage_error
:
procedure handle_received_foo (Foo_In: in Foo.T_Foo) is
begin
Foo.do_something (Foo_Object => Foo_In); -- The storage error does happen here.
end main;
当 运行 使用 gdb 的代码时,我在进入函数时遇到段错误,我得到:
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 39 (LWP 39)]
0x033c9828 in foo.do_something (foo_object=...) at ./foo.adb:67
67 procedure do_something (Foo_Object : in T_Foo);
(gdb) p foo_object
(null)
所以我想我在做参数 Foo_Object
.
storage_error
我知道这不是 MWE,派生类型中使用的其中一种类型可能存在错误。
我找不到任何好的选择:
使
T_Foo
成为Controlled
类型以在Adjust
中调用Copy
似乎是不可能的,除非我尽可能地大幅改变它的定义' t 从T_Base
和Ada.Finalization.Controlled
派生T_Foo
因为其中 none 是接口类型定义
T_Base
为type T_Base is abstract new Ada.Finalization.Controlled with null record;
并覆盖
Adjust
这里似乎对现有代码库进行了大量修改,因为在多个地方产生了 gnattype of aggregate has private ancestor "Controlled" must use extension aggregate.
所以我没有进一步调查问题或用锤子解决问题的解决方案。
问题不在 Copy
函数中。我在代码库中看到的注释具有误导性。
引入新变量改变异常位置的事实让我考虑了一些堆栈溢出问题。
确实为任务分配的 Storage_Size
是不够的。增加 pragma Storage_Size(<value>)
解决了问题。
由于代码库是用-fstack-check
编译的,这导致了前面提到的STORAGE_ERROR
。
更多信息on Adacore's documentation。
这可能已经在 Gem #95: Dynamic Stack Analysis in GNAT 中看到了,但我目前无法看到其中建议的绑定选项的任何结果。