【问题标题】:C Array Segmentation Faults only after a certain thresholdC Array Segmentation Faults 仅在某个阈值之后
【发布时间】:2014-06-28 22:26:25
【问题描述】:

我正在研究这个简单的程序。我的理解是,尝试修改超过最大索引的内存地址的值应该会导致分段错误。但是,以下代码运行没有任何问题。我什至可以打印出所有 6 个数组索引 0->6

main()
{
  int i;
  int a[3];

  for(i=0; i<6; i++)
        a[i] = i;

}

但是,当我将 for 循环更改为

for(i=0; i<7; i++)

并执行程序,它会出现段错误。 在我看来,这几乎就像是 malloc 完成的某种额外填充。 为什么这种情况只发生在第 6 个索引 (s+6) 之后?这种行为会发生在更长/更短的数组中吗?请原谅我作为低级 java 程序员的愚蠢:)

【问题讨论】:

  • 这是什么环境?例如 - 在 MSVC Debug 构建中,为每个分配的块进行了大量填充以检测内存访问违规。在您的特定情况下,可能只是系统可分配的 minimal 内存量恰好是 sizeof(int)*6
  • 在访问数组外的内存时看到的任何行为都是未定义的行为/不可靠的。它很可能会在下一次运行时崩溃,或者可靠地工作数年,直到那个非常糟糕的崩溃时间。
  • 通过汇编运行您的代码并阅读编译器生成的内容 - 这应该为您提供一些很好的见解,了解为什么它会以这种方式工作

标签: c arrays segmentation-fault


【解决方案1】:

在我看来,这几乎就像是 malloc 完成的某种额外填充。

你没有调用 malloc()。您将 a 声明为堆栈内存中的 3 个整数数组,而 malloc() 使用堆内存。在这两种情况下,访问最后一个元素(在本例中为第三个元素,a[2])之后的任何元素都是未定义的行为。当使用堆内存完成时,通常会导致分段错误。

【讨论】:

  • 我似乎认为 malloc() 和声明一个数组是一样的。我不知道为什么。看来我还有很多阅读内容!
【解决方案2】:

好吧,malloc 没有这样做,因为你没有打电话给 malloc。我的猜测是,额外的三个写入足以咀嚼您的帧指针和堆栈指针,但不是通过您的返回地址(但第七个命中)。当您访问越界内存时,您的程序不能保证崩溃(尽管有其他语言可以保证),但不能保证不会崩溃。这就是未定义的行为:不可预测。

【讨论】:

    【解决方案3】:

    正如其他人所说,访问超出其限制的数组是未定义的行为。那么会发生什么?如果您访问不应访问的内存,则取决于该内存的位置。

    通常(但非常普遍,具体情况可能因系统和编译器而异),可能会发生以下主要情况:

    • 您可以简单地访问直接位于数组“后面”的进程的其他变量。如果您写入该内存,您只需修改其他变量的值。您可能不会遇到段错误,因此您可能永远不会注意到为什么您的程序会产生错误的结果或行为如此奇怪,或者为什么在调试期间您的变量具有您从未(有意)分配给它们的值。国际海事组织,这真的很糟糕,因为你认为一切都很好,而实际上并非如此。
    • 您可以访问堆栈上的其他数据,尤其是在堆栈上,例如保存的处理器寄存器,甚至是函数结束时处理器应返回的地址。如果你用一些其他数据覆盖这些,很难说会发生什么。在这种情况下,段错误可能是所有可能的弊端中较小的一个。你根本不知道会发生什么。
    • 如果您的阵列之外的内存不属于您的进程,那么在大多数现代计算机上,您将遇到段错误或类似异常(例如访问冲突,或您的操作系统所称的任何内容)。

    我可能已经忘记了可能发生的其他一些问题,但在 IMO 中,如果超出数组范围编写,这些是最常见的情况。

    【讨论】:

      【解决方案4】:

      这取决于可用的空闲内存,如果可用的空闲内存较少,则会出现分段错误,否则它将使用额外的内存来存储数据并且不会出现分段错误。不需要 malloc,因为数组本身分配内存。

      在您的系统中,内存仅可用于 6 个整数,当您尝试访问下一个内存(不可访问或说不可用)时,它会出现分段错误。

      【讨论】:

      • 空闲内存通常取自堆。这是一个堆栈问题。如果您访问超出其限制的数组,则不必出现分段错误。段错误只是可能的结果之一。
      • @AnujGarg - 从您的回答历史来看,您似乎习惯于提供几乎没有解释的答案,或者完全基于错误事实的答案。在您决定回答下一个问题之前,请记住这一点
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多