1

我有这个看起来像的c程序。

int indexLength;
char *args[1024];
while(args[indexLength])
     indexLength++;

如果我在工作时在计算机下运行程序,while 循环行会给我一个段错误..并且 indexLength 采用一些荒谬的任意值。但是如果我在家里的 linux 机器上运行程序,没有段错误,我的程序运行正常。

我能想到的 2 台机器之间的唯一区别是,工作中的那台具有 gcc4.7 redhat 版本,并且正在运行 Fedora OS,而我家的机器具有从 ppa 存储库下载的 gcc4.7,并且正在运行 ubuntu OS。但是,我不相信这是唯一的区别!会是什么?

编辑:对不起,我忘了提。如果我初始化 indexLength = 0..

4

2 回答 2

5

从未初始化的内存中读取是未定义的行为。变量默认情况下不会初始化,因此indexLength在分配之前可以取任何值。由于行为未定义,程序可以在某些机器上运行,而在其他机器上崩溃。

此外,即使将 初始化indexLength为零也不能修复未定义的行为,因为args仍然未初始化。这意味着程序可能不会在到达数组末尾时停止,并且访问超过分配区域末尾的值。当然,为了做到这一点,包含 1024 个项目的数组中的所有值都必须为非零,因此很有可能在到达数组末尾之前停止。但是,为了解决这种未定义的行为,您需要在访问值之前检查索引。

于 2013-05-22T12:52:18.317 回答
3

您的代码调用未定义的行为

  • args未初始化,因此每个元素都包含不可预测的值。也许你会在下一个 4k 的堆栈中找到一个 NULL 指针并退出循环;也许你不会,你会读到数组末尾之外
  • indexLength未初始化,因此您可以立即读取超出数组末尾的内容
  • 读完结尾的效果args也是不可预知的。这包括潜在的崩溃,比如在达到进程的可读内存限制之前没有找到零字

尽管最初出现,设置indexLength=0实际上并没有使您的代码安全。您仍在读取未初始化的内存,因此依赖于在内部找到 NULL 元素args。没有办法保证你会找到这个。如果您的循环在到达数组末尾之前没有退出,那么您将回到未定义的行为,因此您的程序可能会在任何进一步的迭代中崩溃。

于 2013-05-22T12:52:24.553 回答