Как изменить размер стека с помощью ulimit или на процесс в Mac OS X для программы C или Ruby? - программирование
Подтвердить что ты не робот

Как изменить размер стека с помощью ulimit или на процесс в Mac OS X для программы C или Ruby?

Кажется, что рекомендуемый способ установить размер стека для программы на языке C или программы Ruby (которая использует стек C), использует ulimit в оболочке Bash. Но

$ ulimit -s
8192

$ ulimit -s 16384
-bash: ulimit: stack size: cannot modify limit: Operation not permitted

и sudo тоже не помогают. Есть ли способ установить его на 16 МБ, 32 МБ или 64 МБ? Я думал, что должен быть способ установить его на вызов программы, а не устанавливать также системный параметр?

В настоящее время 8192, вероятно, означает 8MB, что довольно мало, если сравнить его с тем, сколько может быть использовано процесс, иногда до 2 ГБ ОЗУ.

( обновленное примечание: ulimit -a может показывать текущие значения).

( update 2: на самом деле это похоже на ulimit -s <value> на оболочку, и если вы установите его в первый раз, это обычно работает. Проблема заключается в том, что вы устанавливаете его во второй раз, то он может вернуть ошибку)

4b9b3361

Ответ 1

По-видимому, существует жесткий предел размера стека для mac os x, взятый из http://lists.apple.com/archives/scitech/2004/Oct/msg00124.html, который был довольно старым, и Im не уверен, что его все еще верно, но для его установки просто назовите ulimit -s hard, его 65532. или около 65 мегабайт.

Я провел несколько испытаний по снежному леопарду, 10.6.8, и, похоже, это правда.

$ ulimit -a
...
stack size              (kbytes, -s) 8192
...
$ ulimit -s 65533
-bash: ulimit: stack size: cannot modify limit: Operation not permitted
$ ulimit -s 65532
$

Я также нашел этот http://linuxtoosx.blogspot.com/2010/10/stack-overflow-increasing-stack-limit.html, хотя я его не тестировал, поэтому не могу сказать об этом много.

Когда приложения потребляют концерты памяти, которые обычно берутся из кучи, стек обычно является резервом для локальных автоматических переменных, которые существуют в течение относительно небольшого количества времени, эквивалентного продолжительности жизни вызова функции, куча - это то место, где большая часть устойчивые данные.

вот быстрый учебник:

#include <stdlib.h>

#define NUMBER_OF_BYTES 10000000 // about 10 megs
void test()
{
   char stack_data[NUMBER_OF_BYTES];          // allocating on the stack.
   char *heap_data = malloc(NUMBER_OF_BYTES); // pointer (heap_data) lives on the stack, the actual data lives on the heap.
}

int main()
{   
    test(); 
    // at this point stack_data[NUMBER_OF_BYTES] and *heap_data have being removed, but malloc(NUMBER_OF_BYTES) persists.
    // depending on the calling convention either main or test are responssible for resetting the stack.
    // on most compilers including gcc, the caller (main) is responssible.

    return 0;
}

$ ulimit -a
...
stack size              (kbytes, -s) 8192
...
$ gcc m.c
$ ./a.out
Segmentation fault
$ ulimit -s hard
$ ./a.out
$

ulimit является временным, вам придется обновлять его каждый раз или обновлять соответствующий bash script, чтобы установить его автоматически.

Как только ulimit установлен, он может быть опущен только никогда.

Ответ 2

Размер стека по умолчанию системы зависит от версии ядра от ядра. Мой 10.7 - 16384, так что ulimit -s 16384 принят моим Mac. Вы можете попробовать sysctl kern.stack_size и отобразить размер стека только для чтения. мой 16384.
Вы можете увидеть эту техническую статью http://developer.apple.com/library/mac/#qa/qa1419/_index.html, чтобы узнать, как изменить размер стека по умолчанию для программы C. Для Ruby, поскольку это язык сценариев, вам нужно увеличить размер стека во время связывания интерпретатора Ruby. За исключением того, что у вас очень глубокие функциональные вызовы или рекурсия или с очень большим массивом и объектами, выделенными в стеке, ваша программа не должна иметь огромного пространства стека. Вместо этого использование кучи или динамического распределения может использовать до 2 ГБ оперативной памяти, как вы пожелаете.

Ответ 3

На мой взгляд, принятый ответ не совсем прав и приводит к постижению понимания, более конкретно последнее утверждение неверно.

Как только ulimit установлен, он может быть опущен только никогда.

Есть действительно мягкие (отображаемые с ulimit -s или ulimit -Ss) и жесткие (отображаемые с ulimit -Hs) ограничениями. Но при установке предела через ulimit -s будут влиять жесткие значения и.

Как только предел жесткий установлен, он может быть только снижен никогда не повышаться, но мягкий предел может быть понижен или поднят при условии, что значение остается ниже жесткого предела.

Это будет работать:

# base values
$ ulimit -s
100
$ ulimit -Hs
100
$ ulimit -Ss
100
# lower soft limit only
$ ulimit -Ss 50
$ ulimit -s
50
$ ulimit -Hs
100
$ ulimit -Ss
50
# raise soft limit only
$ ulimit -Ss 100
$ ulimit -s
100
$ ulimit -Hs
100
$ ulimit -Ss
100
# lower soft and hard limit
$ ulimit -s 50
$ ulimit -s
50
$ ulimit -Hs
50
$ ulimit -Ss
50
# then impossible to raise soft limit due to hard limit
$ ulimit -s 100
-bash: ulimit: stack size: cannot modify limit: Operation not permitted
$ ulimit -Ss 100
-bash: ulimit: stack size: cannot modify limit: Invalid argument

Ответ 4

Я обнаружил, что с помощью /bin/zsh вместо /bin/sh эта ошибка исчезла.

Для меня ошибка произошла в оболочке script, которая называется ulimit -s unlimited. Когда script интерпретировался на /bin/sh (т.е. Имел #!/bin/sh в качестве первой строки файла script), он блокировал эту ошибку. В отличие от этого, когда вы меняли его на использование zsh, все, казалось, работало нормально. zsh был достаточно умен, чтобы интерпретировать unlimited как "дать мне самый большой предел, который операционная система позволит мне", и все работало так, как вам бы хотелось.