【问题标题】:Ada program works in Linux but not in GPS Windows 10Ada 程序在 Linux 中有效,但在 GPS Windows 10 中无效
【发布时间】:2016-09-17 09:08:13
【问题描述】:

提前感谢您的帮助。我目前正在做一些关于 ada 编程的初学者工作,我已经从http://libre.adacore.com/download/configurations# 安装了 GNAT Programming Studio (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 OS(32 位)。安装了 GNAT 工具,用 gnatmake 编译,用 ./periodictasks 运行,猜猜看,程序做了它应该做的事情并打印出信息。

经过这么长的故事,有人知道为什么会这样吗?会不会是 64 位 vs 32 位的情况?

非常感谢!

【问题讨论】:

    标签: linux windows cpu ada affinity


    【解决方案1】:

    直到最近,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);
    

    在主程序的开头。

    【讨论】:

    • 值得注意的是,旧的行为对于 Ada 编译器是不正确的。直到最近,如果您将“-gnato”参数传递给 GNAT,它还只是一个 Ada 编译器。
    • 非常感谢!!!!!!!我修改了项目 -> 构建属性,添加了 -gnato0 开关及其工作!非常感谢!
    • 我现在遇到了一个稍微不同的问题。 (我应该发布另一个问题吗?)无论我添加 -gnato0 还是将 Integer 更改为 Long_Long_Integer,每当我在 GPS 环境中运行程序时,它都会挂起。如果我“在外部终端中运行”(这是我从一开始就拥有的)程序运行,但是,在执行开始时会打印垃圾,并且打印信息的唯一任务是 Task_P20 和 Task_P18。在 Ubuntu 中,所有任务至少打印一次信息!再次感谢!
    • @AlejandroMartinez:我已经解决了您修改后的问题here 的一部分;你应该相应地编辑这个问题;对任何剩余的问题提出一个新问题。
    【解决方案2】:

    在执行开始时,有垃圾打印,打印信息的唯一任务是Task_P20 & Task_P18

    正如§9.2 Task Execution - Task Activation 中所讨论的,这些任务在PeriodicTasks 的第一条语句执行之前一起激活。尽管所有任务都在运行,但不,部分或所有任务可能会在Start 初始化之前尝试产生输出。至少,将Start 初始化为尽可能接近其声明,

    Start : Time := Clock;
    

    让身体空着,

    begin
        null;
    end PeriodicTasks;
    

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

    【讨论】:

    • 非常感谢!我唯一不明白的是为什么这只发生在 Windows 而不是 Ubuntu 虚拟机中。我可以对 Windows 环境做些什么来使其表现得像 Ubuntu VM 或其他方式。我会发布另一个问题。再次感谢!
    • 一个erroneous 程序可能跨平台行为不一致;我希望更正后的程序能够始终如一地执行。
    猜你喜欢
    • 2014-10-23
    • 2020-04-14
    • 1970-01-01
    • 1970-01-01
    • 2012-03-26
    • 1970-01-01
    • 1970-01-01
    • 2021-06-06
    • 1970-01-01
    相关资源
    最近更新 更多