Сегменты ошибок Bash на brk()
Может кто-нибудь объяснить, почему этот "бесконечный" цикл segfaults быстро? Например, допустим, у нас есть эта функция:
#!/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
Мои вопросы:
- это segfaulting, потому что он пытается получить доступ к не отображенной области в пространстве памяти (через brk)?
- Если да, то почему он пытается получить к нему доступ?
- Будет ли malloc() лучшим выбором здесь?
- Если у вас есть какая-либо дополнительная / пустяковая информация по этому вопросу, это будет оценено.
2 ответа
brk
с не связаны. Это segfaults, потому что ему не хватает места в стеке. Если вы уменьшите доступный стек сulimit -s 512; ./yourscript
вы увидите, что он падает намного быстрее.Он поглощает все пространство стека, потому что у вас бесконечно рекурсивная функция, а bash не выполняет оптимизацию хвостовых вызовов.
Он уже использует
malloc
(или его конкретная версия bash). посколькуmalloc
функция библиотеки C, а не системный вызов, она не отображается вstrace
, Однако с распределенной памятью проблем нет, ей не хватает места в стеке.brk
Они используются для хранения некоторых бесконечных метаданных, связанных с вашей бесконечной рекурсией, но этого недостаточно, чтобы иметь значение.Сбои в бесконечно рекурсивных функциях происходят в различных формах на всех языках, когда у вас есть неограниченная рекурсия, которая не оптимизирована. Пытаться
void foo() { foo(); }
на Java илиdef foo(): foo()
в Python.
Похоже, то, что вы видите, - это стек, растущий до истощения ресурсов. Короче говоря, это проблема рекурсии.
Посмотрите на вызов brk(), и вы увидите, что он меняет конец сегмента данных процесса. Увеличение разрыва программы - это выделение памяти для процесса, но у вас нет неиссякаемого запаса. Когда у вас кончается, он падает.
Но что касается вашего третьего вопроса, даже раздел примечаний в документации предполагает, что malloc() - лучший выбор.