Ada 静态声明上的异常\u访问\u冲突

Ada 静态声明上的异常\u访问\u冲突,ada,Ada,我对***地址使用***的用法不熟悉。我想知道这种用法的局限性是什么。因此,我创建了以下过程: procedure letshack (A : System.Address) is My_String : String(1..100000); for My_String'Address use A; begin Put(My_String); end; 这会引发一个异常\u访问\u冲突,而字符串长度为100的同一代码不会引发它。如果我不使用整

我对***地址使用***的用法不熟悉。我想知道这种用法的局限性是什么。因此,我创建了以下过程:

procedure letshack (A : System.Address) is 
      My_String : String(1..100000);
      for My_String'Address use A;
   begin 
      Put(My_String);
   end;
这会引发一个
异常\u访问\u冲突
,而字符串长度为100的同一代码不会引发它。如果我不使用整数地址,这段代码工作正常

那么,***地址使用***的限制是什么呢。 Ps:我正在使用Ada 95,但欢迎提供任何信息

编辑: 我理解这种行为的一部分。这就是我想的。 当您启动程序时,会分配一个特定的堆栈,您可以在其中写入和读取。实际上,我用一个整数地址写了第5个字节

Real Addresses |----------------------------| Virtual Addresses
        0x48000|Stack Origine               |0x00
               |                            |
               |                            |
               |                            |
               |                            |
               |End of Stack                |
  0x48000+range|----------------------------|0x00+range

如果超出堆栈,则会出现异常访问冲突。对于一种“强势”语言来说,如果它是正确的,那似乎很奇怪。因为这意味着您可以重写自己的堆栈并做出不好的行为。

如果您已经确保从
a开始在内存的可读部分分配了100000个连续字符,那么它应该可以工作


如果
A
是另一个Ada实体的地址,则它不应该工作。

最终发现了该行为。 启动程序时,使用的地址是页面中的虚拟地址。 系统中处理虚拟地址的部分用于分配给进程的特定大小的内存,该内存根据系统的不同而保持不变,如下图所示:

Real Addresses |----------------------------| Virtual Addresses
        0x48000|Begin of the virtual address|0x00
               |range                       |
               |                            |
               |                            |
               |End of the virtual address  |
               |range                       |
  0x48000+range|----------------------------|0x00+range
您可以在不分配变量的情况下执行任何操作。例如,在我的windows上,根据
中的变量
si.dwPageSize
,此大小为
4096字节。

我测试了字符串的长度可以是4096字节,但不能是4097字节。我现在必须在我的嵌入式系统上测试它,但似乎接近事实

这可能取决于调用,特别是A的实际调用,而不是过程本身。做一个演示。显然,如果整个字符串不属于您的进程,那么就会发生一些不好的事情。如果你想写一个病毒,有比Ada更好的语言:-)每当你做这样的地址覆盖,你也应该做一个
pragma导入(Ada,My_String)(或等效方面),以防止覆盖对象(本例中为My_字符串)的任何默认初始化@BrianDrummond汇编语言除外,因为地址计算、位大小问题、检查抑制等的可能性在标准Ada中既可用又明确,编写一个记录在案的病毒可以利用Ada的功能获利。借助SPARKAda,病毒的算法甚至可能得到验证。如果一个人真正想做的是在专业环境中编写病毒,这似乎并不糟糕。@BrianDrummond我不是在尝试制作病毒:)),我是在关键实时环境中尝试避免异常。所以我的问题是,是什么规定了这种用法的构成。限制是什么。对于最小的、完整的和可验证的示例。我希望能够做到这一点,但我不理解这种行为。正如在文章中所说的,如果我给这个过程一个整数地址,它在字符串长度为100_000时不起作用,但在字符串长度为100时它起作用(两个长度都不是整数长度)。如果使用Gnat,则使用-fstack check编译(以及一堆其他标志,我忘了让它正确地符合Ada)。任何其他操作都需要按照您建议的方式使用MCVE(传递整数的地址)。但最好的方法是准确地确定为什么需要SYSTEM.ADDRESS。你几乎肯定不会。我的问题是,当我给过程一个整数地址时,当字符串长度为100时,它工作。这看起来很奇怪。接下来的96个字节是否已分配?或者这与在未分配内存中写入相同?您可能很幸运,100个字符位于同一内存页上。如果您可以控制内存分配(在操作系统级别上),则可以使用任意大的对象进行控制。我已经用几百万个字符的字符串完成了。是的,我刚刚写了一个答案,似乎是关于页面的。但它似乎没有那么幸运,因为字符串可以在程序中放置的任何位置生成4096。