C 中未初始化指针到底有什么危险

ber*_*436 4 c pointers initialization

我正在尝试通过 Jim Trevor 的PL 课程“ Cyclone:C 的安全方言”来掌握 C。Trevor 和他的合著者正在尝试制作 C 的安全版本,因此他们消除了语言中未初始化的指针。谷歌搜索了一下未初始化的指针,似乎未初始化的指针指向内存中的随机位置。看来仅此一点就让他们不安全了。如果引用未初始化的指针,则会跳转到内存的不安全部分。时期。但特雷弗谈论它们的方式似乎暗示事情更为复杂。他引用了以下代码,并解释说,当函数 FrmGetObjectIndex 取消引用 f 时,它不是在访问有效指针,而是在访问一个不可预测的地址 \xe2\x80\x94,无论 f 的空间在堆栈上是什么,被分配了。

\n\n

Trevor 所说的“分配 f 空间时堆栈上的内容”是什么意思?默认情况下,“未初始化”指针是否初始化为内存中的随机位置?或者它们的“随机”行为是否与分配给这些指针的内存由于堆栈上的意外行为而填充了奇怪的值(然后引用)有关。

\n\n
Form *f;\n   switch (event->eType) {\n   case frmOpenEvent:\n   f = FrmGetActiveForm(); ...\n   case ctlSelectEvent:\n   i = FrmGetObjectIndex(f, field); ...\n}\n
Run Code Online (Sandbox Code Playgroud)\n

Pas*_*uoq 5

Trevor 所说的“分配 f 空间时堆栈上的内容”是什么意思?

他的意思是,在大多数汇编语言中,使用单独的指令在堆栈上保留空间并在新保留的空间内写入初始值。如果 C 程序使用未初始化的变量,则该程序通常会会在运行时执行保留堆栈空间的指令,但不会执行设置堆栈空间的指令。当使用指针时,它实际上包含保留空间之前堆栈上的位模式。在好的情况下,这将是一个无效地址。在糟糕的情况下,这将恰好是一个有效的地址,并且影响将是不可预测的。

这只是一个典型的行为。从理论上来看,使用不确定的值是未定义的行为。比简单地访问无效地址或有效地址更奇怪的事情可能会发生(意外故意使用未初始化数据(不是地址)的示例)。


以下是 C 的受限子集(例如 Cyclone)旨在防止的危险:

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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在最后一条危险线中,实际上,很可能将 4 写入变量block_local,但实际上,在第二次迭代时,p是不确定的,程序不应该访问*p,并且当访问时,它是未定义的行为。