Brk()上的Bash脚本段错误

时间:2017-12-28 16:27:06

标签: c linux bash malloc brk

有人可以解释为什么这个“无休止”的循环段快速崩溃了吗? 例如,假设我们有这个功能:

#!/bin/bash

foo() {
  foo 
}; foo

8-10 秒后的段错误。通过strace检查,我们可以看到很多 brk()来电:

brk(0x2e11000)                          = 0x2e11000
brk(0x2e12000)                          = 0x2e12000
brk(0x2e13000)                          = 0x2e13000
brk(0x2e14000)                          = 0x2e14000
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x7ffcddf5ff68} ---
+++ killed by SIGSEGV +++
Segmentation fault

我的问题是:

  1. 是这个segfaulting,因为它试图访问内存空间中的未映射区域(通过brk)?
  2. 如果是,为什么要尝试访问它?
  3. malloc()会在这里成为更好的选择吗?
  4. 如果您对此有任何额外/琐事信息,我们将不胜感激。

2 个答案:

答案 0 :(得分:3)

  1. brk s无关。它是段错误的,因为它耗尽了堆栈空间。如果您使用ulimit -s 512; ./yourscript减少可用堆栈,则会发现它崩溃得更快。

  2. 它吞噬了所有堆栈空间,因为你有一个无限递归函数,而bash不进行尾调用优化。

  3. 它已使用malloc(或其特定版本的bash)。由于malloc是C库函数而不是系统调用,因此它不会显示在strace中。分配的内存没有问题,但是它的堆栈空间不足。

  4. brk用于存储与无限递归相关的一些无限元数据,但这并不重要。

    无限递归函数中的崩溃在所有语言中以各种形式发生,当您进行无限制的递归时,未进行优化。在Java中尝试void foo() { foo(); },或在Python中尝试def foo(): foo()

答案 1 :(得分:0)

看起来你所看到的是堆栈不断增长,直到资源耗尽。简而言之,这是一个递归问题。

查看brk()来电,您会看到它正在改变流程数据段的结尾。增加程序中断是为进程分配内存,但是你没有取之不尽的用途。当你用光时,它会崩溃。

但至于你的第三个问题,即使是文档中的注释部分也表明malloc()是更好的选择。