【问题标题】:Segmentation fault with ulimit set correctlyulimit 设置正确的分段错误
【发布时间】:2015-09-26 09:17:35
【问题描述】:

我试图帮助this question 上的 OP。

我发现即使堆栈设置为 2000 KB,像下面这样的代码也会随机导致分段错误。

int main ()
{
   int a[510000];
   a[509999] = 1;
   printf("%d", a[509999]);
   return 0;
}

如您所见,数组为510000 x 4 bytes = 2040000 bytes。

使用 ulimit 命令将堆栈设置为 2000 KB(2048000 字节):

  • ulimit -s 2000
  • ulimit -Ss 2000

基于这些数字,应用程序有空间存储数组,但随机返回分段错误。

有什么想法吗?

【问题讨论】:

  • 也许stdio的数据结构应该与环境等一起考虑
  • @EdHeal 你能详细说明一下吗?
  • 这取决于实现,在您的情况下,程序确实使用了 stdio 库。可以在 main 被命中之前使用堆栈来存储东西。这可能包括atexit 等的指针。
  • @EdHeal 我明白,但那东西可能超过 8000 字节吗?
  • @EdHeal:在main 的条目上使用一些内联汇编打印出rsp 寄存器的值。通过这种方式,您可以确定到目前为止已使用了多少堆栈。

标签: c segmentation-fault stack


【解决方案1】:

您不能这样做有几个原因。有些东西已经在使用你的堆栈。

main 不是你堆栈中的第一件事。在 main 之前有一些被真正入口点、动态链接器等调用的函数,它们可能都在使用一些堆栈。

此外,通常可以将一些东西放在堆栈顶部以设置执行。我知道的许多系统都将所有字符串放在 argv 中,并将所有环境变量放在堆栈顶部(这就是为什么 main 不是入口点的原因,通常在 main 之前运行的代码会为 main 设置环境变量和 argv)。

如果您的系统这样做,可能会故意浪费一部分堆栈以增加 ASLR 的随机性。

在调试器中运行您的程序,在 main 处添加一个断点,查找堆栈寄存器的值并检查其上方的内存(请记住,除非您使用的是奇怪的架构,否则您的堆栈很可能会变小)。我打赌你会在那里找到很多指针和字符串。我只是在 linux 系统上做的,因为我怀疑我所有的环境变量都在那里。

Unix 上的资源限制 (ulimit) 的目的从未真正将事物微观管理到一个字节/微秒,它们只是为了阻止你的程序完全疯狂并用它来破坏整个系统。不要将它们视为正确道路上的红灯和停车标志,而应将它们视为跑道上的跑​​道和防撞护栏。

【讨论】:

    【解决方案2】:

    如果您仍想访问数组中的 int 位置,请尝试在没有 main 的情况下编译代码。这将不会调用 _start

    查看此讨论enter link description here

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-09-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-18
      • 2013-03-24
      • 2019-08-01
      相关资源
      最近更新 更多