Ada 在编译时确保异常覆盖率
有没有办法让GNAT确保所有异常情况都得到处理 举个例子:Ada 在编译时确保异常覆盖率,ada,Ada,有没有办法让GNAT确保所有异常情况都得到处理 举个例子: package IO renames Ada.Text_IO; package EIO renames Ada.IO_Exceptions; procedure Open_File (File : in out IO.File_Type) is begin IO.Open (File, IO.In_File, "example.txt"); exception
package IO renames Ada.Text_IO;
package EIO renames Ada.IO_Exceptions;
procedure Open_File (File : in out IO.File_Type) is
begin
IO.Open (File, IO.In_File, "example.txt");
exception
when EIO.Use_Error =>
IO.Put_Line ("Use!");
when EIO.Device_Error =>
IO.Put_Line ("Device!");
end Open_File;
Open
还可能引发Name\u错误
,因此我想提醒GNAT案件尚未处理
我发现pragma限制(无异常传播)
但这似乎也将检查应用于标准库调用,因此Open
变得不可用,因为它本身传播异常。如果我将此应用于我的示例,我会得到:
14:07: warning: pragma Restrictions (No_Exception_Propagation) in effect
14:07: warning: this handler can never be entered, and has been removed
16:07: warning: pragma Restrictions (No_Exception_Propagation) in effect
16:07: warning: this handler can never be entered, and has been removed
举例说明我想从另一种语言中得到什么;Nim有一个
raises
pragma来注释一个过程可以引发哪些异常,这些异常由编译器强制执行。列表可以为空,即,引发:[]
,编译器将要求处理所有异常,而不是传播。Ada中是否有与此等效的程序?如果您想处理所有可用的异常,可以在异常
部分中的其他异常时使用。您的示例如下所示:
package IO renames Ada.Text_IO;
package EIO renames Ada.IO_Exceptions;
procedure Open_File (File : in out IO.File_Type) is
begin
IO.Open (File, IO.In_File, "example.txt");
exception
when An_Exception : others =>
IO.Put_Line (EIO.Exception_Message(An_Exception));
end Open_File;
如果希望以单独的方式处理每个异常,那么必须单独列出每个异常(如示例中所示)。但编译器不会警告您缺少异常处理程序。这在Ada中是不可能的
Nim之所以能够做到这一点,是因为引发的杂注是函数签名的一部分。因此,对于任何调用,静态地知道可以引发哪些异常。Ada的情况并非如此
如果您认为编译器可以隐式地找出任何子例程可以引发哪些异常,这是正确的,但并不能解决问题,因为Ada同时允许调度调用和函数指针。对于这两种情况,您都无法静态地知道将调用的函数(没有指针分析,这超出了大多数编译器的范围),因此无法知道可能引发的异常(因为它们不是签名的一部分)。使用SPARK,通过证明不会引发任何异常,您可以保证所有异常都在程序的SPARK verified部分中得到处理……编译器无法确定会引发哪些异常。c.l.a.的一位撰稿人指出,Storage\u Error
总是有可能被引发的(例如,通过堆栈溢出,我怀疑SPARK也能阻止它)@SimonWright,这只意味着编译器告诉您,任何分配数据的操作都可以引发Storage\u Error
(就像任何除法运算都可能产生约束错误一样)。这更多的是一种理论上的评论;Ada的模块化编译模型禁止传播这种源于身体的知识,因为编译单元只知道其他单元的规范。有语言(例如Zig)这确实将存储错误
视为一个推断错误和签名的一部分。不必是分配,至少不必是从堆中:如果您声明一个长度为整数的字符串'Last
,那么获得存储错误
将是令人高兴的,而不是一个非常模糊的内存破坏。类似的情况会发生因为我认为Unchecked\u转换
只提供了对象的备用视图,而不是在堆栈上创建副本(此行为可能受优化级别的影响)