[c, win] char c[n] против char* c=HeapAlloc(..., n)

feliks28

Задумался: а вот бывает нужно передать функции неинициализированный буфер длины n для записи в него.
Конструкция char c[n]; во первых проще выглядит, во вторых ассемблерный код (и как следствие exe'шник) получается короче. А что происходит при выполнении?
Какая из двух сабжевых конструкций шустрее/стабильнее? Они отличаются вообще?

Maurog

я не профи, но есть мысль, что
char c[n];
создается на стеке и давать доступ к стеку в другой функции крайне небезопасно.

yolki

char c[n] даёт большую нагрузку на стек (велика вероятность схлопотать Stack overflow) при n>~1kb.

FRider

э... Это конечно зависит от ОС, но в винде вроде стек порядка 1Мб...

Maurog

Post deleted by

FRider

и?

Maurog

мне всегда казалось, что размер стека определяет компилятор, а не операционка :confused:

yolki

а если эта функция окажется в рекурсии с глубиной эдак в 1000?

klyv

то её надо оптимизировать по памяти ;)

feliks28

В общем итоговая мысль какая? Использовать массивы только если они меньше X байтов и не участвуют в рекурсии? Тогда для различных операционных систем (или все же компиляторов?) какое примерное X?

banderon

В Linux:
dsme ~ $ ulimit -s
8192

8 Мб на весь стек

kruzer25

В винде:
$ ulimit -s
unlimited

:D

feliks28

Эммм, на весь стек - это на все программы одновременно ? :crazy:

feliks28

А по умолчанию сколько? Компиляторозависимо?
У меня на gcc(без опций) объявление ~двухмегабайтного(только для теста) массива крашится, а других компиляторов у меня нет.

pitrik2

Эммм, на весь стек - это на все программы одновременно ? :crazy:
на каждую естессно
этот параметр можно изменять под рутом

Oper

Народ вы чо, с ума сошли? Массивы в C перелаются по ссылке, а не по значению.
Если надо передавать по значению — необходимо заворачивать в структуру.

pitrik2

А по умолчанию сколько?
я бы посоветовал не париться
если пишешь утилиту на скору руку, то юзаешь стековый вариант и не паришься
если пишешь серьезную прогу "на века" то стековый вариант вообще не юзаешь
если пишешь супер отимизированную по скорости прогу - то читай соотв. книжки, статьи, алгоритмы там все есть

pitrik2

Народ вы чо, с ума сошли? Массивы в C перелаются по ссылке, а не по значению.
здесь речь не про передачу а про инициализацию
где сам массив в памяти лежит?

Oper

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

evgen5555

Инициализация отличается только в ассемблерном коде - DEC ESP, N и PUSH N - CALL HeapAlloc

pitrik2

блин
внимательно читай тред сначала

Oper

Прочитал несколько раз. То, что хочет топикстартер — непонятно.
Хотя бы примеры привел.

ppplva

Функция, в ней локальная переменная - массив, либо динамический либо на стеке. Рекурсия.

Oper

нужно передать функции неинициализированный буфер длины n
То есть неявно подразумевается, что этот массив будет потом использоваться в родительской функции.
Про рекурсию не увидел ни слова ;)

Oper

Функция, в ней локальная переменная - массив, либо динамический либо на стеке. Рекурсия.
В такой постановке все, конечно, зависит от длины массива.

feliks28

Ну, вот если я на скорую руку пишу рекурсивный поиск на диске (функция принимает два указателя: где ищем и что ищем то париться или нет?
А вообще, когда я вопрос задавал, то у меня была ситуация: объявляем 8-килобайтный массив, содержащий описание ошибки под виндой, передаем его паре функций (отображающих это описание пользователю) и освобождаем память (HeapFree для HeapAlloc или оборачиваем в { } для массива).
Тут как я понял париться не стоит, да?

pitrik2

То, что хочет топикстартер — непонятно.
топикстартер спрашивает в чем отличие

void f {
char c[N];
}

и

void f {
char* c = HeapAlloc(..., N);
}

ответ: в первом случае массив создается в стеке, который довольно маленький и следовательно длина массива не может быть большой
зато работает быстрее
во втором случае создается в куче, длина зависит от кол-ва оперативки
чем отличается стек от кучи читай тут: http://en.wikipedia.org/wiki/Dynamic_memory_allocation
http://en.wikipedia.org/wiki/Stack-based_memory_allocation

ppplva

char* c=HeapAlloc(..., n)

Здесь явно рассматривается способ создания (размещения) массива, а не способ его передачи.

Oper

не поверишь, я отлично знаю, чем отличается стек от кучи :smirk:

pitrik2

тогда чего мне голову морочишь что перечитал тред и не понял про что он?

Oper

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

feliks28

Автору нужно было понять общий принцип, а не получить готовую программу. Так что не надо на меня все валить.
Если я ни слова про что-то (рекурсию) не написал - это вовсе не значит, что я не хочу про это "что-то" получить дополнительные знания ;)
p.s. Загадил мне тут хороший тред :( Споря с тобой, мои никто и не заметил :crazy:

pitrik2

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

Oper

ну извини, зато будешь выражать свои мысли яснее в следующий раз

feliks28

Ну, сразу всему же не научишься, так зачем ошибки плодить? Потом меньше переписывать.
А какой нерекурсивный вариант? Побитовое чтение подряд файловой системы?
Оставить комментарий
Имя или ник:
Комментарий: