LINUX.ORG.RU

Максимально допустимый размер массива на стеке?

 


3

7

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

Какой то вот такой кривой пример кода:

int Nmax = 1024; // максимально возможный размер буфера на стеке
void func(){
  int N = ...;
  T p_buf[(N<=Nmax)*N];
  T* p = p_buf; if(N>Nmax) p = new T[N];
  ...
  if(N>Nmax) delete [] p;
}

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

Deleted ()
Ответ на: комментарий от AntonI

В общем случае ты не можешь узнать размер стека. Си++ такой возможности не предоставляет. Из-под Линукса можешь почитать про getrlimilt(). Вроде там было что-то про размер стека. А может я и вру всё...

Deleted ()
Ответ на: комментарий от Deleted

Вроде были какие то опции компиляции задающие размер стека? Хотя это тоже не вариант, на стеке много всего может висеть..

AntonI ()
Ответ на: комментарий от AntonI

на стеке много всего может висеть..

Вот именно.
Так что просто выдели достаточно большой буфер, котрый будет покрывать 80% твоих потребностей, а в остальных 20% выделяй память лишь на время работы функции.

Deleted ()
Ответ на: комментарий от Deleted

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

AntonI ()
Ответ на: комментарий от AntonI

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

deep-purple ★★★★★ ()
Ответ на: комментарий от Deleted

Ок, спасибо;-)

Но все таки это местами избыточно…

AntonI ()

хочется создавать его на стеке (что бы не дергать менеджер памяти)

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

А вот за такой стиль, с забором вместо ясного и понятного значения или имени переменной/константы:

T p_buf[(N<=Nmax)*N];

надо бить написавшего по рукам.

seiken ★★★★★ ()

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

(thread_local) static + нормальный аллокатор(mmap). Либо можно пожрать говна и с вектором. Либо есть уже готовые реализация подобной дристни boost::small_vector

p_buf[(N<=Nmax)*N];

В крестах нет vla - поэтому либо не юзай, либо юзай аллоку.

anonymous ()
Ответ на: комментарий от seiken

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

Эти бездарные потуги запарных бездарностей. Запомни раз и навсегда - закукарекал о «преждевременная» и об «оптимизация» - определил себя за биомусор. Никто иной такой херни не несёт.

А вот за такой стиль, с забором вместо ясного и понятного значения или имени переменной/константы:

Сталь действительно говно, но ты не о нём. То, что ты, обезьяна, не осилила (N <= Nmax) * N - это твоя проблема, а не того, кто это написал. Конечно, там где ты полы моешь такое никто не напишет, но то проблема бездарности поломоев, повторю.

надо бить написавшего по рукам.

Нет, просто бездарное говно должно знать своё место.

anonymous ()

Максимально допустимый размер массива на стеке?

Пока не упадёт. Если мегабайт выделил, а программа не упала, значит, допустимо.

i-rinat ★★★★★ ()
Ответ на: комментарий от AntonI

Не юзай мейнпоток для вычислений. Создавай потоки и руками прикручивай стек. Тогда там будет столько памяти, сколько тебе нужно. Хоть бесконечное кол-во. И уже в них запускай вычисления.

anonymous ()
Ответ на: комментарий от anonymous

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

anonymous ()

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

dave ★★★★★ ()
Ответ на: комментарий от AntonI

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

Задача похожа на арифметику для первоклассников. У Васи было десять яблок. Он отдал Пете три. Сколько яблок осталось у Васи?

Ты правда хочешь, чтобы тебе объясняли, как из десяти вычесть три?

i-rinat ★★★★★ ()
Ответ на: комментарий от i-rinat

Нет, я к сожалению не знаю ответа - иначе бы я не спрашивал.

Аналогия у приличных людей не является ни аргументом, ни доказательством.

AntonI ()
Последнее исправление: AntonI (всего исправлений: 1)
Ответ на: комментарий от AntonI

у приличных людей

Ха!

Серьёзно. Не хочу слышать о приличиях от человека, который не соизволил в поисковик вбить «how to figure out stack size on linux». В первом же результате написано про uname -s и getrlimit.

i-rinat ★★★★★ ()

Будь мужиком сделай свой стэк.

pon4ik ★★★★★ ()
Ответ на: комментарий от AntonI

Ты её что, часто делаешь? Если да, у меня для тебя плохие новости. В противном случае тебе должно быть всё равно

XMs ★★★★★ ()
Ответ на: комментарий от AntonI

выделение памяти в куче - это дорогая операция

Так выдели один раз и используй как собственный стек сколько хочешь раз.

foror ★★★★ ()
Ответ на: комментарий от anonymous

Запомни раз и навсегда - закукарекал о «преждевременная» и об «оптимизация» - определил себя за биомусор. Никто иной такой херни не несёт.

Запомни сам, херню несешь здесь только ты.

rumgot ★★★★★ ()

Дефолтный размер стека зависит от операционной системы, по памяти в линуксе 8МиБ, на винде 1МиБ, но это всё можно крутить в обе стороны

Harald ★★★★★ ()
Ответ на: комментарий от Harald

Да, и вот тут у меня два вопроса:

  1. какие негативные последствия будут при увеличении стека?
  2. можно ли как то понять сколько памяти на стеке свободно?
AntonI ()
Ответ на: комментарий от AntonI

1. Вроде никаких

2. Переносимых способов нет, можно вычесть из текущего указателя на стек начальное значение указателя на стек

Harald ★★★★★ ()
Ответ на: комментарий от AntonI

Статистика и профилирование. Первое покажет сколько кб, а второе что ты херней занимаешься.

anonymous ()
Ответ на: комментарий от anonymous

Определяют на, а не за, пацанчик. Таких как ты в нормальной хате сразу на младшего тестировщика определяют.

anonymous ()
Ответ на: комментарий от AntonI

При линковке.

Вроде были какие то опции компиляции задающие размер стека?

При линковке. Например, так:

gcc -Wl,--stack,9437184 -o you_app you_app.c

Пожалуйста, стек в 9 Mb. Можно и через LD_FLAGS определить, но да, это крайне плохое решение.

Про getrlimit() тут, как я погляжу, уже написали, можно в приложении выставить свой размер стека принудительно. Примерно так (man setrlimit()):

#include <sys/resource.h>

int main (int argc, char **argv)
{
    const rlim_t my_size = 9 * 1024 * 1024;   /* Те же 9Mb */
    struct rlimit rl;
    int result;

    result = getrlimit(RLIMIT_STACK, &rl);
    if (result == 0)
    {
        if (rl.rlim_cur < my_size)
        {
            rl.rlim_cur = my_size;
            result = setrlimit(RLIMIT_STACK, &rl);
            if (result != 0)
            {
                fprintf(stderr, "Error! setrlimit() returned result = %d\n", result);
            }
        }
    }
    /* Do something here. */
    return 0;
}

Т.е., прямо в main() предупредили систему что Ваша приблуда работает со стеком в 9Mb и дальше просто используйте ф-ю alloca(), забыв о malloc/calloc/new и т.д. и т.п. Выставлять каждый раз заново размер стека не получится, тут нужно сразу прикинуть сколько по максимуму памяти может понадобиться. И, если на пролезет в стек, то просить у системы память под непролазящую в стек порцию данных. Т.е., высегда смотреть на размер приходящих данных – юольше 9M или меньше и, если > 9, то тогда calloc/malloc, всё как обычно.

Дополнительный профит здесь – вызов alloca() не требует очистки памяти по free(). Т.е., получили память в своей ф-ии, вышли из неё, считайте за Вами прибрано. Но и вернуть такой массив из своей ф-ии запросто не получится. А так, в принципе, этот вариант чуть быстрее и чуть экономичнее стандартного выделения памяти в куче, но и несколько менее надёжный.

В общем, тоже вариант так себе.

Moisha_Liberman ()
Последнее исправление: Moisha_Liberman (всего исправлений: 1)
Ответ на: комментарий от rumgot

Ты местная достопримечательность.

А ты местное нонейм-говно.

Как алкаш на роликах, изрекающий забавные глуповатые мысли.

Нет, алкаш ты - ты клоун, которого тут держат подобные тебе бездарные холопы.

Запомни, маня, у тебя течёт методичка. Алкаша на ютубе смотрят, а меня то не смотрят. Смотрят именно тебя, говно. Никто не выгоняет и не глушит клоунов.

anonymous ()
Ответ на: комментарий от Deleted

Во-во! Мегабайт оперативы выделить, а если не хватит — realloc'ом еще мегабайт добавить…

OnlyAsk ()
Ответ на: комментарий от AntonI

Да ладно Вам!

А в чем будет заключаться непереносимость?

Не знаю зачем, но зачем-то народ с этой переносимостью носится как дураки с писаной торбой.

Если так надо будет под винды из-под Linux перенести, то используйте MinGW, да и не парьтесь. По большей части там переносимо.

Однако, если уж писать именно под Linux, то лучше не ограничивать себя в средствах, специфичных именно для Linux. А под винды… под винды есть сисярп.

Moisha_Liberman ()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)