Я читал, что это зависит от архитектуры компилятора и операционной системы. Как узнать максимальный размер сегмента данных и стека в системе Linux, используя GCC в качестве компилятора?
Позвольте мне поэкспериментировать с вами: создайте файл « test.c » следующим образом:
int main (void) { return 0; }
Теперь скомпилируйте его, указав максимальный размер стека (просто для поиска этого числа в файле карты и определения имени символа, ссылаясь на него):
gcc test.c -o test.x -Wl,--stack=0x20000 -Wl,-Map=output.map
Определить размер данных просто:
size -A -d test.x
Вы получите что-то вроде этого:
section size addr
.text 1880 4299165696
.data 104 4299169792
...
Также « objdump -h test.x » будет работать нормально, но с менее подробными результатами.
Здесь есть больше разделов (не только код и данные), но здесь нет информации о стеке. Зачем? Поскольку размер стека не является разделом ELF, он зарезервирован только после загрузки вашей программы для выполнения. Вы должны прочитать его из некоторого (зависимого от платформы) символа в вашем файле, например:
$ nm test.x | grep __size_of_stack_reserve__
0000000000020000 A __size_of_stack_reserve__
Не удивительно, что этот размер равен 0x20000, как было указано при компиляции.
Я определил имя символа, посмотрев в файл output.map, который был сгенерирован во время компиляции. Я также рекомендую начать с рассмотрения.
Далее, когда у вас есть какой-то неизвестный файл a.out, просто повторите последовательность:
size -A -d a.out
nm a.out | grep __size_of_stack_reserve__
Подставляя платформо-зависимый символ этому, вы определили в эксперименте, описанном выше.
Сегменты — это метод организации вещей, которые нужны вашему исполняемому файлу.
Сегмент данных обычно предназначен для любых данных, которые использует ваш исполняемый файл (без ввода из внешних источников). Некоторые сегменты данных могут содержать строковые литералы или числовые константы.
Многие исполняемые файлы используют стек для хранения локальных переменных функций, локальных переменных блоков операторов, адресов возврата и параметров функций. Стек не требуется языками C или C ++; это просто удобная структура данных.
размер стека может быть либо емкость, выделенная стеку, либо количество элементов, находящихся в стеке, либо объем памяти, занимаемый стеком.
Многие платформы имеют размер по умолчанию для стека. Поскольку платформы различаются, вам необходимо прочитать документацию по своим инструментам, чтобы узнать, как установить размер стека и какова емкость по умолчанию.
Как узнать максимальный размер сегмента данных и стека в системе Linux, используя GCC в качестве компилятора?
Эти пределы можно прочитать как RLIMIT_DATA
а также RLIMIT_STACK
пределы ресурса getrlimit
.
В командной строке вы можете использовать ulimit
Команда, чтобы найти эти ограничения вашей системы:
$ ulimit -s # stack
8515
$ ulimit -d # data
unlimited
Вы можете изменить системные ограничения, изменив limits.conf.
И еще в man pthread_create
:
В Linux / x86-32 размер стека по умолчанию для нового потока составляет 2 мегабайта. Согласно реализации многопоточности NPTL, если ограничение мягкого ресурса RLIMIT_STACK во время запуска программы имеет какое-либо значение, отличное от «unlimited», то оно определяет размер стека по умолчанию для новых потоков. Используя pthread_attr_setstacksize (3), атрибут размера стека может быть явно установлен в аргументе attr, используемом для создания потока, чтобы получить размер стека, отличный от значения по умолчанию.
И в man ld
:
—стек резерв
—резервировать стек, фиксировать
Укажите количество байтов памяти, которые нужно зарезервировать (и при необходимости зафиксировать) для использования в качестве стека для этой программы. По умолчанию зарезервировано 2 МБ, зафиксировано 4 КБ. [Эта опция специфична для целевого порта i386 PE компоновщика]