gpt4 book ai didi

ada - 使用不能被 8 整除的模类型时引发 Constraint_Error

转载 作者:行者123 更新时间:2023-12-03 13:53:02 25 4
gpt4 key购买 nike

我遇到了一个问题,即在 Ada 中使用不能被系统的 Storage_Unit 整除的模块化类型。 (在运行时的 system.ads 中定义)将引发 Constraint_Error在运行时访问时。我最初在使用最小运行时间的裸机系统上工作时遇到了这个问题,同时尝试通过将 12 位数组覆盖在内存中的缓冲区上来从缓冲区读取 12 位值。有谁知道为什么会这样?

以下最小示例说明了我遇到的问题。我使用 AdaCore 的 GNAT 2019 进行了测试,使用包含的 zfp 编译运行。使用标准运行时不会重现该问题。

with Ada.Text_IO; use Ada.Text_IO;

procedure Main is
----------------------------------------------------------------------------
-- Modular type with standard size divisible by 8.
----------------------------------------------------------------------------
type Type_One is mod 2 ** 16;
type Buffer_Type_One is array (1 .. 128) of Type_One;

----------------------------------------------------------------------------
-- Modular type with non-base 8 size.
----------------------------------------------------------------------------
type Type_Two is mod 2 ** 12;
type Buffer_Type_Two is array (1 .. 128) of Type_Two;

type Buffer is array (1 .. 256) of Character;

----------------------------------------------------------------------------
-- Example buffer.
----------------------------------------------------------------------------
Test_Buffer : Buffer := (others => ' ');
begin
----------------------------------------------------------------------------
-- Will not raise an exception.
----------------------------------------------------------------------------
Test_One :
declare
Buffer_One : Buffer_Type_One
with Import,
Convention => Ada,
Address => Test_Buffer'Address;
begin
Put_Line ("Testing type one");
for I in Natural range 1 .. 16 loop
Put_Line ("Test: " & Buffer_One (I)'Image);
end loop;
end Test_One;

----------------------------------------------------------------------------
-- Will raise a constraint error at runtime.
----------------------------------------------------------------------------
Test_Two :
declare
Buffer_Two : Buffer_Type_Two
with Import,
Convention => Ada,
Address => Test_Buffer'Address;
begin
Put_Line ("Testing type two");
for I in Natural range 1 .. 16 loop
Put_Line ("Test: " & Buffer_Two (I)'Image);
end loop;
exception
when Constraint_Error =>
Put_Line ("Constraint error encountered.");
end Test_Two;

end Main;

这是我用来编译这个例子的项目文件:
project Test is

for Object_Dir use "obj";
for Exec_Dir use "build";
for Create_Missing_Dirs use "True";

for Languages use ("Ada");

package Builder is
for Executable ("main.adb") use "test";
end Builder;

for Main use ("main.adb");

package Compiler is
for Default_Switches ("Ada") use (
"-gnat2012",
"-gnatwadehl",
"-gnatVa",
"-gnaty3abcdefhiklmnoprstux"
);
end Compiler;

for Runtime ("Ada") use "zfp";
end Test;

我似乎在 RM 中找不到任何可以说明为什么会发生这种情况的东西。

编辑:下面的西蒙赖特已经弄清楚为什么会发生这种情况。我天真的理解是 Buffer_Type_Two 的一个实例覆盖在指定的内存地址会将该位置的内存解释为 12 位值的序列。看来情况并非如此。似乎编译器将类型的大小四舍五入到 16 位,然后提高 Constraint_Error当从数组中读取的 16bit 值不符合 12bit 类型时。

如果有人能想到一种更好的方法来按顺序从内存中的某个位置读取一系列 12 位值,我将不胜感激,谢谢。

最佳答案

使用最近的 GNAT,您可以通过定义 Buffer_Type_Two 来实现您想要的行为。作为

type Buffer_Type_Two is array (1 .. 128) of Type_Two
with Pack;

ARM 13.2(9)警告说,对于 13 位值,这可能无法满足您的要求(不过,最近的 GNAT 会这样做)。

另一种选择是
type Buffer_Type_Two is array (1 .. 128) of Type_Two
with Component_Size => 12;

结果是
...
Testing type two
Test: 32
Test: 514
Test: 32
Test: 514
...

对于 13 位,无论采用哪种方法,
...
Testing type two
Test: 32
Test: 257
Test: 2056
Test: 64
Test: 514
Test: 4112
Test: 128
Test: 1028
Test: 32
...

但是,对于嵌入式目标,您需要使用 -full-运行时系统;对于其他人,正如上面@egilhh 所指出的,
ajxs.adb:14:09: packing of 12-bit components not supported by configuration

关于ada - 使用不能被 8 整除的模类型时引发 Constraint_Error,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61933040/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com