使用存储管理器进行内存分配导致不是纯函数 (RM 13.1(22))
Memory allocation with storage manager leads to not pure function (RM 13.1(22))
将一些旧代码移植到较新的 CentOs Linux 机器上。
我正在使用带有几个标志的 linux gnat:
Default_Switches ("ada") use ("-fstack-check", "-g", "-gnatVr", "-gnato", "-gnatE", "-gnatwmuv", "-gnata", "-m32");
我有 gnat 版本:
gcc-gnat.i686 4.8.5-11.el7
所以这些是先决条件。
我现在有一个可以正常工作的自写存储管理器,由
调用
St_Wa.Alloc(StoragePool, BitSize)
现在我的问题是,老实说,我真的不明白为什么编译器会失败,所以如果能详细解释为什么它不起作用,我将不胜感激!
function AllocMem(StoragePool : in St_Wa.Mem_Pool_Type;
Option: in Option_Type)
return Option_Ref is
subtype New_Type is Option_Type (Option.Kind);
New_Option : New_Type;
for New_Option use at St_Wa.Alloc( StoragePool => StoragePool,
BitSize => New_Type'Size)
begin
Bl_Bl.Move( ... sth happens here ... )
return Pointer(New_Option'Address);
end AllocMem;
鉴于:
type Option_Type ( Kind : Option_Kind_Type := Marker) is
record
Next : Option_Ref;
case Kind is
when First_Procedure => First_Procedure : First_Procedure_Type;
when Sec_Procedure => Sec_Procedure : Sec_Procedure_Type;
end case;
end record;
我收到以下错误:
invalid address clause for initialized object "New_Option"
function "Alloc" is not pure (RM 13.1 (22))
我收到这个错误是因为我有一个带有条件的类型的开关盒,因此大小只取决于种类吗?如何在不重写所有内容的情况下避免这种情况?
Do I get this error because I have a switch case in the type with conditions and therefore the size is only determined depending on kind?
没有。 LRM 中错误消息 (RM 13.1 (22)) 引用的段落内容如下:
An implementation need not support representation items containing nonstatic expressions, except that an implementation should support a representation item for a given entity if each nonstatic expression in the representation item is a name that statically denotes a constant declared before the entity.
现在,这里的表示项是对 Alloc
的调用,因为您的代码:
for New_Option use at St_Wa.Alloc(StoragePool => StoragePool,
BitSize => New_Type'Size);
是
的 Ada83 风格
for New_Option'Address use St_Wa.Alloc(StoragePool => StoragePool,
BitSize => New_Type'Size);
并且由于 Alloc (...)
是函数调用,它不是静态表达式,因为根据 RM 4.9,静态函数是:
- a predefined operator whose parameter and result types are all scalar types none of which are descendants of formal scalar types;
- a predefined concatenation operator whose result type is a string type;
- an enumeration literal;
- a language-defined attribute that is a function, if the prefix denotes a static scalar subtype, and if the parameter and result types are scalar.
由于Alloc
是上面的none,如RM 13.1 所述,实现不需要在表示项中支持它。然而,实际的错误消息告诉我们 "Alloc" 不是纯的 ,所以 GNAT 告诉它如果 Alloc
是纯的它会支持这个。
因此解决此问题的一种方法是使 Alloc
纯净,这意味着:将 pragma Pure;
添加到包含 Alloc
的包 St_Wa
中。这是否可能取决于包,它可能需要额外的更改。
如果这不可行,RM 13.1 (22) 以另一种方式暗示:如果非静态表达式表示在实体之前声明的常量,则应支持该表达式。因此,这应该有效:
My_Address : constant System.Address :=
St_Wa.Alloc(StoragePool => StoragePool, BitSize => New_Type'Size);
New_Option : New_Type;
for New_Option use at My_Address;
将一些旧代码移植到较新的 CentOs Linux 机器上。 我正在使用带有几个标志的 linux gnat:
Default_Switches ("ada") use ("-fstack-check", "-g", "-gnatVr", "-gnato", "-gnatE", "-gnatwmuv", "-gnata", "-m32");
我有 gnat 版本:
gcc-gnat.i686 4.8.5-11.el7
所以这些是先决条件。 我现在有一个可以正常工作的自写存储管理器,由
调用St_Wa.Alloc(StoragePool, BitSize)
现在我的问题是,老实说,我真的不明白为什么编译器会失败,所以如果能详细解释为什么它不起作用,我将不胜感激!
function AllocMem(StoragePool : in St_Wa.Mem_Pool_Type;
Option: in Option_Type)
return Option_Ref is
subtype New_Type is Option_Type (Option.Kind);
New_Option : New_Type;
for New_Option use at St_Wa.Alloc( StoragePool => StoragePool,
BitSize => New_Type'Size)
begin
Bl_Bl.Move( ... sth happens here ... )
return Pointer(New_Option'Address);
end AllocMem;
鉴于:
type Option_Type ( Kind : Option_Kind_Type := Marker) is
record
Next : Option_Ref;
case Kind is
when First_Procedure => First_Procedure : First_Procedure_Type;
when Sec_Procedure => Sec_Procedure : Sec_Procedure_Type;
end case;
end record;
我收到以下错误:
invalid address clause for initialized object "New_Option"
function "Alloc" is not pure (RM 13.1 (22))
我收到这个错误是因为我有一个带有条件的类型的开关盒,因此大小只取决于种类吗?如何在不重写所有内容的情况下避免这种情况?
Do I get this error because I have a switch case in the type with conditions and therefore the size is only determined depending on kind?
没有。 LRM 中错误消息 (RM 13.1 (22)) 引用的段落内容如下:
An implementation need not support representation items containing nonstatic expressions, except that an implementation should support a representation item for a given entity if each nonstatic expression in the representation item is a name that statically denotes a constant declared before the entity.
现在,这里的表示项是对 Alloc
的调用,因为您的代码:
for New_Option use at St_Wa.Alloc(StoragePool => StoragePool,
BitSize => New_Type'Size);
是
的 Ada83 风格for New_Option'Address use St_Wa.Alloc(StoragePool => StoragePool,
BitSize => New_Type'Size);
并且由于 Alloc (...)
是函数调用,它不是静态表达式,因为根据 RM 4.9,静态函数是:
- a predefined operator whose parameter and result types are all scalar types none of which are descendants of formal scalar types;
- a predefined concatenation operator whose result type is a string type;
- an enumeration literal;
- a language-defined attribute that is a function, if the prefix denotes a static scalar subtype, and if the parameter and result types are scalar.
由于Alloc
是上面的none,如RM 13.1 所述,实现不需要在表示项中支持它。然而,实际的错误消息告诉我们 "Alloc" 不是纯的 ,所以 GNAT 告诉它如果 Alloc
是纯的它会支持这个。
因此解决此问题的一种方法是使 Alloc
纯净,这意味着:将 pragma Pure;
添加到包含 Alloc
的包 St_Wa
中。这是否可能取决于包,它可能需要额外的更改。
如果这不可行,RM 13.1 (22) 以另一种方式暗示:如果非静态表达式表示在实体之前声明的常量,则应支持该表达式。因此,这应该有效:
My_Address : constant System.Address :=
St_Wa.Alloc(StoragePool => StoragePool, BitSize => New_Type'Size);
New_Option : New_Type;
for New_Option use at My_Address;