我正试着通过Jim Trevor的“Cyclone: A safe dialect of C”为PL课程工作。特雷弗和他的合着者正试图制作一个安全的C版本,因此他们用他们的语言消除了未初始化的指针。对于未初始化的指针Googling around a bit,似乎未初始化的指针指向内存中的随机位置。似乎这一点使他们不安全。如果你引用一个非itilialized指针,你跳转到一个不安全的内存部分。期。但特雷弗谈论它们的方式似乎暗示它更复杂。他引用了下面的代码,并解释了当函数FrmGetObjectIndex解引用f时,它不是访问有效指针,而是访问一个不可预测的地址 - 当分配f空间时堆栈上的任何内容。
Trevor的意思是“当分配f的空间时,堆叠中的任何东西”?默认情况下,“未初始化”指针是否已初始化为内存中的随机位置?或者他们的“随机”行为是否与为这些指针分配的内存有关,因为堆栈上的意外行为会填充奇怪的值(然后被引用)。
Form *f;
switch (event->eType) {
case frmOpenEvent:
f = FrmGetActiveForm(); ...
case ctlSelectEvent:
i = FrmGetObjectIndex(f, field); ...
}
答案 0 :(得分:4)
Trevor的意思是“当f的空间被分配时,堆叠中的任何东西”?
他的意思是在大多数汇编语言中,使用单独的指令来保留堆栈上的空间并在新保留的空间内写入初始值。如果C程序使用未初始化的变量,程序将在运行时通常执行保留堆栈空间但没有设置它的指令的指令。当使用指针时,它将字面上包含在保留空间之前堆栈上的位模式。在好的情况下,这将是一个无效的地址。在不好的情况下,这将恰好是一个有效的地址,并且效果将是不可预测的。
这只是一种典型行为。从理论的角度来看,使用不确定的值是未定义的行为。除了简单地访问无效地址或有效地址之外,可能会发生许多奇怪的事情(使用未初始化数据(不是地址)的示例使用accidentally或purposely)。
以下是Cyclone旨在阻止C等受限子集的危险:
int a, *p;
int main(int c, char **v){
int l, *lp, i;
if (c & 1)
a = l + 1; // danger
if (c & 2)
*lp = 3; // danger
if (c & 4)
{
p = &a;
for (i=0; i<=1; i++)
{
int block_local;
*p = 4; // danger
p = &block_local;
}
}
}
在最后一个危险的行中,实际上,很可能将4写入变量block_local
,但实际上,在第二次迭代中,p
是不确定的,程序不是应该访问*p
,并且它是未定义的行为。
答案 1 :(得分:0)
在现代操作系统上,危险是核心转储。在没有内存管理的早期系统上,可能存储器映射到外部硬件的i / o,危险程度完全不同。