Ada 使用访问类型在受保护对象中调用过程时出现问题
考虑显示对同一过程的三个不同调用的附加代码。它编译良好,但在执行时挂起。我怀疑有某种锁,但我不明白为什么Ada 使用访问类型在受保护对象中调用过程时出现问题,ada,Ada,考虑显示对同一过程的三个不同调用的附加代码。它编译良好,但在执行时挂起。我怀疑有某种锁,但我不明白为什么 with Ada.Text_IO; use Ada.Text_IO; with Ada.Exceptions; use Ada.Exceptions; procedure Main is type A_Proc is access protected procedure (B: in out Integer); protected Obj is procedure
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Exceptions; use Ada.Exceptions;
procedure Main is
type A_Proc is access protected procedure (B: in out Integer);
protected Obj is
procedure Inc (B: in out Integer);
procedure Test (B: in out Integer);
end Obj;
protected body Obj is
procedure Inc (B: in out Integer) is
begin
B:=B+1;
end Inc;
procedure Test (B: in out Integer) is
Proc : A_Proc:=Inc'Access;
begin
Proc.all (B);
end Test;
end Obj;
B : Integer:=1;
Proc : A_Proc:=Obj.Inc'Access;
begin
Put_Line(B'Image);
Obj.Inc (B);
Put_Line(B'Image);
Proc.all (B);
Put_Line(B'Image);
Obj.Test (B);
Put_Line(B'Image);
Put_Line("The End");
end Main;
在这方面,我们发现
对于在受保护子程序上执行调用,[…]如果调用是内部调用(见9.5),则子程序的主体将与普通子程序调用一样执行。如果调用是外部调用,则子程序主体将作为目标受保护对象上新受保护操作的一部分执行
而在
当名称或前缀表示条目、受保护子程序时,[…]名称或前缀确定目标对象,如下所示:
- 如果是表示操作声明(或主体)的直接名称或扩展名称,则隐式指定目标对象为立即包含该操作的任务或受保护单元的当前实例;使用这种名称的调用被定义为内部调用
- 如果名称或前缀是对受保护子程序值的访问的取消引用(隐式或显式),则目标对象由最初生成访问值的访问属性_引用的前缀确定;使用此名称的调用被定义为外部调用
所以我担心手臂会明确警告你不要做什么
Obj
在进入Obj时被锁定。Test
,通过Proc
的外部调用尝试再次锁定。参见。作为西蒙·赖特答案的附录,我认为
在受保护的操作期间,调用可能阻塞的操作是有界错误。以下被定义为潜在的阻塞操作:
[……]
- 对与受保护动作具有相同目标对象的受保护子程序(或外部请求)的外部调用李>
详细说明以下注释:您可以使用配置pragma
Detect\u Blocking
对这些潜在阻塞调用进行Ada运行时检查(请参阅)
如果使用GPRbuild,则可以通过放置pragma Detect\u Blocking来启用检测将>编码到文件(通常名为gnat.adc
)中,并通过向编译器包添加Local\u configuration\u Pragmas
属性,在项目文件中引用此配置文件(另请参见和):
当我编译并运行它时,它就工作了。您使用的是什么版本的工具?更重要的是,我想,@JimRogers,您使用的是什么版本?我知道在您的另一个问题中,您在处理字符串到过程调用的映射。如果这是您仍然感兴趣的内容,您是否希望了解如何将此示例转换为可以使用字符串调用过程的内容?Simon已经回答了“为什么”,所以我基本上是在问,如果你想要这样的东西,更新你的问题,以反映你可能想要什么样的解决方案来解决这个问题。我有一些想法,但它们取决于您的实际需求。我使用的是托管在x86_64-pc-mingw32 GNAT Community 2018(20180523-73)@JimRogers上的GPS 2018(20180523),在Debian stretch上使用相同(但日期为..0525)编译器,在macOS上打印“3”行后挂起,配置pragmaDetect\u Blocking
)导致PE被引发。希望您不介意,我冒昧地编辑了您的链接,直接引用ARM段落到引用(19),将\p19
添加到URL的末尾。这只适用于2012版ARM(可能还有更高版本)。@SimonWright不,一点也不,谢谢你提供关于URL的提示。对于pragmaDetect_Blocking
:Linux和Windows上的行为相同;出现程序错误
。
project Default is
for Source_Dirs use ("src");
for Object_Dir use "obj";
for Main use ("main.adb");
package Compiler is
for Local_Configuration_Pragmas use "gnat.adc";
end Compiler;
end Default;