Ada程序在Linux上可以运行,但在GPS Windows 10上无法运行。

4

感谢您的帮助。我目前正在学习ada编程的入门知识,已经从http://libre.adacore.com/download/configurations#下载并安装了GNAT编程工具包(GPS)。 我的系统是Windows 10 64位。在学校里,老师给了我以下代码:

pragma Task_Dispatching_Policy(FIFO_Within_Priorities);

with Ada.Text_IO; use Ada.Text_IO;
with Ada.Real_Time; use Ada.Real_Time;

procedure PeriodicTasks is

    Start : Time;

    package Duration_IO is new Ada.Text_IO.Fixed_IO(Duration);
    package Int_IO is new Ada.Text_IO.Integer_IO(Integer);

    task type T(Id: Integer; Period : Integer) is
        pragma Priority(Id);
    end;

    task body T is
        Next : Time;
        X : Integer;
    begin
        Next := Start;
        loop
            Next := Next + Milliseconds(Period);
            -- Some dummy function
            X := 0;
            for Index in 1..5000000 loop
                X := X + Index;
            end loop;
            Duration_IO.Put(To_Duration(Clock - Start), 3, 3);
            Put(" : ");
            Int_IO.Put(Id, 2);
            Put_Line("");
            delay until Next;
        end loop;
    end T;

    -- Example Task
    Task_P10 : T(10, 250);
    Task_P12 : T(12, 500);
    Task_P14 : T(14, 500);
    Task_P16 : T(16, 250);
    Task_P18 : T(18, 500);
    Task_P20 : T(20, 250);
begin
    Start := Clock;
    null;
end PeriodicTasks;

我在GPS中打开了文件,进行了构建(没有错误),并运行了它,但没有显示任何输出。我听说有时候多核CPU会出现问题,所以每次打开gps.exe时,CPU亲和力被设置为仅一个CPU,并且始终以管理员身份运行。然而,这也没有起作用,我没有得到任何输出。
我决定使用Oracle Virtual Box,并设置了一个仅有一个处理器的Ubuntu操作系统(32位)。安装了GNAT工具,使用gnatmake编译,使用./periodictasks运行,猜猜看,程序做了它应该做的事情并打印出信息。
经过这么长时间的故事后,有没有人知道为什么会出现这种情况?可能是64位与32位的问题吗?
非常感谢!
2个回答

2

最近,GNAT默认不检查整数溢出。它确实会检查约束错误,例如将0赋值给Positive

我们中的许多人认为编译器开发人员这是一个奇怪的选择,因为它导致了许多问题,其根本原因是未能处理整数溢出。最近的更改使我们认为开发人员现在同意了!

您的问题出在语句上:

for Index in 1..5000000 loop
   X := X + Index;
end loop;

这将得到X〜10 ^ 13,这不适合32位整数(它适合64位整数,但在大多数GNAT平台上都是Long_Long_Integer)。

你的Windows编译器很可能是GNAT GPL 2016,显示新行为,而Ubuntu编译器是旧版FSF GCC。

您可以使用编译器开关-gnato0告诉Windows编译器使用旧的行为。

您可以使用编译器开关-gnato告诉Ubuntu编译器使用新的行为。

要在任务中处理未处理的异常消息(否则会默默死亡),请添加

GNAT.Exception_Traces.Trace_On (GNAT.Exception_Traces.Unhandled_Raise);

在你的主程序开始处。

1
值得注意的是,旧行为对于Ada编译器来说是不正确的。直到最近,只有在传递了“-gnato”参数时,GNAT才是一个Ada编译器。 - Jacob Sparre Andersen
1
请参阅§8.4 GNAT中的溢出检查处理 - trashgod
非常感谢!!!我修改了项目->构建属性,添加了-gnato0开关,现在它可以工作了!非常感谢! - Alejandro Martinez
我现在有一个稍微不同的问题。(我应该发布另一个问题吗?)无论我添加-gnato0还是将Integer更改为Long_Long_Integer,每当我在GPS环境内运行程序时它都会挂起。如果我在“外部终端中运行”(这就是我从一开始就拥有的方式),程序会运行,但是,在执行开始时会打印出垃圾信息,并且唯一打印信息的任务是Task_P20和Task_P18。在Ubuntu中,所有任务至少都会输出一次信息!再次感谢! - Alejandro Martinez
@AlejandroMartinez:我已经在这里回答了你修改后问题的一部分(https://dev59.com/35rga4cB1Zd3GeqPstbF#39559827);你应该相应地编辑这个问题;对于任何剩余的问题,请提出一个新的问题。 - trashgod

2
执行开始时,会打印垃圾信息,只有Task_P20Task_P18会打印信息。
§9.2 任务执行 - 任务激活所讨论的那样,在PeriodicTasks的第一条语句执行之前,所有任务都会被同时激活。尽管所有任务都在运行,但是在初始化Start之前,可能会没有、部分或全部任务试图产生输出。至少要在其声明附近初始化Start
Start : Time := Clock;

并且将主体留空。

begin
    null;
end PeriodicTasks;

此外,未能激活的任务将成为已完成的任务,不会产生任何输出。

非常感谢!我仍然不明白的唯一一件事是为什么这只发生在Windows而不是Ubuntu虚拟机中。我该怎么做才能让Windows环境表现得像Ubuntu VM或者反过来呢?我会发布另一个问题。再次感谢! - Alejandro Martinez
一个错误的程序在不同平台上可能表现不一致;我期望修正后的程序能够始终如一地执行。 - trashgod

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接