Как рассчитать оставшийся размер стека? [Дубликат]

11
задан johnbakers 22 June 2013 в 13:53
поделиться

5 ответов

В поле * nix используйте getrlimit :

   RLIMIT_STACK
          The maximum size of the process stack, in bytes.  Upon
          reaching this limit, a SIGSEGV signal is generated.  To handle
          this signal, a process must employ an alternate signal stack
          (sigaltstack(2)).

В Windows используйте VirtualQuery :

Для первого вызова передайте ему адрес любого значения в стеке, чтобы получить базовый адрес и размер в байтах зарезервированного пространства стека. На машине x86, где стек растет вниз, вычитайте размер с базового адреса и VirtualQuery еще раз: это даст вам размер пространства, зарезервированного для стека (если вы не точно на пределе размера стека в то время ). Суммирование двух естественно дает вам общий размер стека.

Нет никакого независимого от платформы метода, поскольку размер стека остается логической реализации и хост-системы - на встроенном мини-SOC есть меньше ресурсов для распространения, чем на 128 ГБ оперативной памяти. Однако вы можете влиять на размер стека определенного потока на всех ОС, а также на вызовы, специфичные для API.

7
ответ дан Community 15 August 2018 в 19:59
поделиться

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

Однако некоторые компиляторы имеют опции для установки размера стека. И платформа может указать, что она делает при запуске процесса, и / или предоставить способы установить размер стека нового потока, возможно, даже манипулировать существующим.

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

1
ответ дан Balog Pal 15 August 2018 в 19:59
поделиться

Возможное переносное решение - написать распределитель самостоятельно. Вам не нужно использовать стек процесса, просто имитируйте его в куче. Выделите большой объем памяти в начале и напишите над ним распределитель стека, чтобы использовать его при распределении. Google «Требования к подписчикам» для получения информации о том, как его достичь на C ++.

Я не уверен, что термин «Stack Allocator» является каноническим, но я имею в виду, что вы должны ставить стеки как ограничения на то, где должно происходить распределение или освобождение. Поскольку вы сказали, что ваш алгоритм подходит для этого шаблона, я думаю, что это будет легко.

5
ответ дан manasij7479 15 August 2018 в 19:59
поделиться

В стандартном C ++ определенно нет. В переносном смысле, вероятно, нет. Иногда в конкретной ОС. Если ничего другого, вы можете открыть свой собственный исполняемый размер и проверить заголовки исполняемого файла, чтобы увидеть, как он стекируется. [Следующая проблема, конечно, «сколько стека использовалось до этого бита кода», что может быть трудно определить).

Если вы запускаете код в отдельном потоке, многие из (нисходящих) потоковых интерфейсов позволяют указать стек (или стекизировать), например, Posix threads pthread_set_stacksize или MS _beginthread . Опять же, вы не знаете ТОЧНО, сколько места было использовано до того, как оно попадет в настоящий код потока, но это, вероятно, не огромная сумма.

Конечно, во встроенной системе (например, мобильном телефоне) стекизация обычно довольно мала, 4K, 12K или 64KB очень обычна, иногда даже намного меньше, чем в некоторых системах.

Еще одна потенциальная проблема заключается в том, что вы не можете действительно знать, сколько пространства фактически используется в стеке - вы можете измерить после факта в скомпилированной системе и, конечно, если у вас есть локальный массив стека из int array[25];, мы можем знать, что он занимает не менее 25 * sizeof(int) - но может быть заполнение, компилятор сохраняет регистры в стеке и т. д. и т. д.

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

 if (enough_stack_space_for_something)
      use_stack_based_algorithm();
 else
      use_heap_based_algorithm();

Это добавит достаточное количество дополнительных накладных расходов, а больше кода, как правило, не является хорошим планом во встроенной / мобильной системе.

Edit2: Кроме того, если выделение памяти является основной частью среды выполнения, возможно, посмотрите, почему это так, например, создание блоков объектов?

2
ответ дан Mats Petersson 15 August 2018 в 19:59
поделиться

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

Стек представляет собой деталь реализации конкретный компьютер / ОС / компилятор. Следовательно, любой метод доступа к меткам стека будет специфичен для машинного / OS / компилятора.

Пока вы не являетесь фактическим ответом на ваш конкретный вопрос (Niels достаточно хорошо это рассмотрели), но как совет для вашей проблемной области: просто выделите большой кусок памяти в куче. Нет никакой причины в стороне от удобства, что «реальный» стек любой другой. Очень рекурсивные (не хвостовые рекурсивные) алгоритмы часто требуют этого, чтобы гарантировать, что у них есть фактически неограниченный «стек». Языки скриптов, которые хотят, чтобы они отображали ошибку / исключение во время выполнения, а не сбой приложения-хоста, также часто делают это. Чтобы быть эффективными в отношении вещей, вы можете либо реализовать «разбитый стек» (например, std::deque даст вам), либо вы можете просто предусмотреть выделение стека, достаточно большого для ваших нужд.

2
ответ дан Sean Middleditch 15 August 2018 в 19:59
поделиться
  • 1
    Нет причин, кроме удобства, что «реальный» стек любой другой. Но часто упоминается, что стек быстрее, чем куча, так что, конечно, это больше, чем удобство? – johnbakers 22 June 2013 в 22:05
  • 2
    Выделения (используя malloc или new или тому подобное) в куче медленнее, чем создание локальной переменной в стеке или использование чего-то вроде alloca. Стек обычно автоматически избегает проблем с фрагментацией и кэш-локацией, которые могут укусить вас при использовании кучи, если вы наивны, но которые не являются проблемой, если вы будете осторожны. Некоторые архитектуры имеют явные инструкции для реализации стека, например. push и pop на x86, но их преимущество будет крайне минимальным в большинстве алгоритмов. Если у вас нет показателей производительности, которые вам нужны, не беспокойтесь об этом. – Sean Middleditch 22 June 2013 в 22:25
Другие вопросы по тегам:

Похожие вопросы: