Ada SPARK中不允许在干扰上下文中调用volatile函数

Ada SPARK中不允许在干扰上下文中调用volatile函数,ada,gnat,spark-ada,Ada,Gnat,Spark Ada,我目前正在大学学习实时编程语言课程,对SPARK有一个问题 我正在做一个项目,任务是监控离网电源。这项任务对于机器安全至关重要,因此应该尽可能避免错误,比如说使用SPARK进行验证。我可以在stackoverflow的其他问题上运行一些东西,但是我仍然遇到了一些错误,我无法通过用户指南中的快速搜索来修复这些错误 错误是SPARK中不允许在干扰上下文中调用volatile函数,如果monitoring\u interface.is\u all\u config\u已设置,则参考该行。。。在 各自的

我目前正在大学学习实时编程语言课程,对SPARK有一个问题

我正在做一个项目,任务是监控离网电源。这项任务对于机器安全至关重要,因此应该尽可能避免错误,比如说使用SPARK进行验证。我可以在stackoverflow的其他问题上运行一些东西,但是我仍然遇到了一些错误,我无法通过用户指南中的快速搜索来修复这些错误

错误是SPARK中不允许在干扰上下文中调用volatile函数,如果monitoring\u interface.is\u all\u config\u已设置,则参考该行。。。在

各自的机构是:

package body PSU_Monitoring is

   protected body Monitoring_Interface_T is

      function is_all_config_set return Boolean is
      begin
         return monitor_pfc_voltage_config_set and monitor_pfc_current_config_set and monitor_output_voltage_config_set and monitor_output_current_config_set;
      end is_all_config_set;

      procedure set_monitor_pfc_voltage_config (new_monitor_config : in Monitor_Config_T) is
      begin
         monitor_pfc_voltage_config := new_monitor_config;
         monitor_pfc_voltage_config_set := True;
      end set_monitor_pfc_voltage_config;

      function get_monitor_pfc_voltage_config return Monitor_Config_T is
      begin
         return monitor_pfc_voltage_config;
      end get_monitor_pfc_voltage_config;

      procedure set_monitor_pfc_current_config (new_monitor_config : in Monitor_Config_T) is
      begin
         monitor_pfc_current_config := new_monitor_config;
         monitor_pfc_current_config_set := True;
      end set_monitor_pfc_current_config;

      function get_monitor_pfc_current_config return Monitor_Config_T is
      begin
         return monitor_pfc_current_config;
      end get_monitor_pfc_current_config;

      procedure set_monitor_output_voltage_config (new_monitor_config : in Monitor_Config_T) is
      begin
         monitor_output_voltage_config := new_monitor_config;
         monitor_output_voltage_config_set := True;
      end set_monitor_output_voltage_config;

      function get_monitor_output_voltage_config return Monitor_Config_T is
      begin
         return monitor_output_voltage_config;
      end get_monitor_output_voltage_config;

      procedure set_monitor_output_current_config (new_monitor_config : in Monitor_Config_T) is
      begin
         monitor_output_current_config := new_monitor_config;
         monitor_output_current_config_set := True;
      end set_monitor_output_current_config;

      function get_monitor_output_current_config return Monitor_Config_T is
      begin
         return monitor_output_current_config;
      end get_monitor_output_current_config;

   end Monitoring_Interface_T;

... Definition of the remaining subprograms defined in the specification file ...

end PSU_Monitoring;

这里的问题是什么?

正如Jeffrey所说,我们需要查看程序中标记错误的部分。一般来说,这与具有副作用的功能有关,请参阅参考手册:

如果您以错误的方式使用Real Time package中的时钟功能,则可以看到相同的错误消息:

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

procedure Main with SPARK_Mode is
    Last : Time := Clock;
begin

    -- some stuff happening here ...

    if Clock > Last + Milliseconds(100) then
        Put_Line("Too late");
    end if;
end Main;
时钟是一个有副作用的函数,每次调用它时它都会返回不同的值,在本例中,该函数用于所谓的干扰上下文中。有关定义,请参见上面的链接

解决方案是稍微重写代码:

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

procedure Main with SPARK_Mode is
    Last : Time := Clock;
begin

    -- some code
    declare
        now : Time := Clock;
    begin      
        if now > Last + Milliseconds(100) then
            Put_Line("Too late");
        end if;
    end;
end Main;

因此,基本上,您要做的是将对具有副作用的函数的调用隔离到一个单独的语句中,将结果保存在一个变量中,然后在以前调用过的地方使用该变量。这个技巧也应该有助于调用受保护对象。

正如Jeffrey所说,我们需要查看程序中标记错误的部分。一般来说,这与具有副作用的功能有关,请参阅参考手册:

如果您以错误的方式使用Real Time package中的时钟功能,则可以看到相同的错误消息:

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

procedure Main with SPARK_Mode is
    Last : Time := Clock;
begin

    -- some stuff happening here ...

    if Clock > Last + Milliseconds(100) then
        Put_Line("Too late");
    end if;
end Main;
时钟是一个有副作用的函数,每次调用它时它都会返回不同的值,在本例中,该函数用于所谓的干扰上下文中。有关定义,请参见上面的链接

解决方案是稍微重写代码:

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

procedure Main with SPARK_Mode is
    Last : Time := Clock;
begin

    -- some code
    declare
        now : Time := Clock;
    begin      
        if now > Last + Milliseconds(100) then
            Put_Line("Too late");
        end if;
    end;
end Main;

因此,基本上,您要做的是将对具有副作用的函数的调用隔离到一个单独的语句中,将结果保存在一个变量中,然后在以前调用过的地方使用该变量。此技巧也有助于调用受保护对象。

提供的代码中没有函数调用。哪一行/哪一列给出了错误消息?啊,你是对的。函数调用在if语句的第三段中提到。下面的块仅说明调用其函数的受保护对象的代码。提供的代码中没有函数调用。哪一行/哪一列给出了错误消息?啊,你是对的。函数调用在if语句的第三段中提到。下面的块仅说明调用其函数的受保护对象的代码。我将请求的代码添加到我的问题中,但您的解释准确无误,已经解决了我的问题。我将请求的代码添加到我的问题中,但您的解释准确无误,已经解决了我的问题。