【发布时间】:2020-11-06 02:56:13
【问题描述】:
我使用一个基于基本包的对象,大致定义为:
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
$1 (null)
所以我想我在对参数Foo_Object 进行浅表复制时会得到一个storage_error。
我知道这不是 MWE,并且派生类型中使用的其中一种类型可能存在错误。
我找不到任何好的选择:
-
如果不大幅更改其定义,我无法从
T_Base和Ada.Finalization.Controlled中派生T_Foo,因此将T_Foo设为Controlled类型以在Adjust中调用Copy似乎是不可能的。它们都不是接口类型 -
将
T_Base定义为type T_Base is abstract new Ada.Finalization.Controlled with null record;并在此处覆盖
Adjust似乎会导致对现有代码库的大量修改,因为 gnat 在多个地方产生了聚合类型具有私有祖先“受控”必须使用扩展聚合。
所以我缺乏进一步调查问题或用锤子解决问题的解决方案。
【问题讨论】:
-
如何将 T_FOO 传递给主程序?如果 main 有一个本地声明并正确初始化的 T_FOO,do_something 调用是否有效?
-
我通过网络获得了 T_FOO。它确实不在我的主程序中(对不起,应该没有调用这个主程序)。 T_Foo 比示例中的复杂得多。但我想我可以比较这种类型的深拷贝和浅拷贝,看看它们是否会产生存储错误。
-
我没有看到对
Copy的任何呼叫。就目前而言,您似乎将null传递给Foo.Do_Something- 不知道这是怎么发生的 -
我可能完全走错了路。对代码进行一些研究以研究副本移动了 storage_error。我正在考虑源于 storage_size 太小的问题,per the doc“对于任务,Storage_Size 子句指定要为任务堆栈分配的空间量。这不能扩展,如果堆栈耗尽,则 Storage_Error将被引发(如果启用堆栈检查)。“在我的情况下,启用了“-fstack-check”......
标签: ada