LINUX.ORG.RU

Динамически выделяемые локальные массивы в c++


0

0

Возник такой вопрос: динамически выделяемые локальные массивы (т. е. место под которые выделяется в стеке) является частью стандарта c или гнутым расширением? К примеру, нижеприведённый код gcc-4.1 нормально компилирует (и он нормально работает), а мелкомягкий компилятор (из msvs) - нет:

int n=10;
double a[n];

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

★★
Ответ на: комментарий от devinull

> попробуй скаомпилить с -ansi и gcc тебе все объяснит.

Компилирует молча, вообще ничего не говорит. Причём в режиме любых стандартов.

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

> Как заставить msvc это скомпилировать ?

Вот у меня вопрос как раз возник потому что msvs это не компилирует. То ли это расширение стандарта, то ли это msvs стандарты не полностью поддерживает...

slav ★★
() автор топика

C99 - является. Раньше, АФАИК, не являлось. С++ - не является.

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

n должна быть константой времени компиляции, конкретно твой пример фиксится так:

const int n=10; 
double a[n];

 

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

> в C++ надо использовать std::vector, а не всякие пережитки С

...за исключением случаев, когда "пережитки" гораздо быстрее ;)

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

Бездумное использование std::vector может весьма негативное сказаться на производительности, т.к. скорость выделения памяти на стеке в разы быстрее.  

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

Это вы сами придумали или прочитали где? Хотя, не сомневаюсь, у вас такое может иметь место. А под стек память выделять не надо? Откуда же она берётся?

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

В каком месте они "гораздо быстрее" ? тесты есть? vector этот тот же массив Си, только завернутый внутрь класса. Если так хочется с ним работать как с double *, то возьми адрес нулевого элемента.

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

> В каком месте они "гораздо быстрее" ?

Если моя память мне ни с кем не изменяет, при создании вектора производится вызов operator new (в случае использования дефолтного аллокатора). При создании массива auto производится арифметическая операция с указателем стека. Вот это и называется "гораздо быстрее".

> тесты есть?

Зачем? В любом случае, спрашивай OP.

> vector этот тот же массив Си, только завернутый внутрь класса.

Да ты что? Нет, правда? :)

> Если так хочется с ним работать как с double *, то возьми адрес нулевого элемента.

И зачем в таком случае использовать vector?

Еще раз: использовать вектор или auto-массив - зависит от обстоятельств.

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

ну так и calloc() тоже инициализирует. дело не в этом - мне было интересно узнать отличие для того, чтобы понять насколько в new добавлено больше накладных расходов по сравнению с тем же malloc()/calloc().

P.S. собственно касательно отличия в скорости - выделение массива в стеке это просто изменения SP и если память для стека выделена то page fault'ов не будет (что очень быстро); в случае malloc()/calloc() я так понимаю добавляются дорогие jump'ы на ф-ции и идут syscall'ы в случае необходимости (двигают brk-адрес) в случае если в пуле недостаточно памяти ну и page-fault'ы тоже возможны тк cow используется. P.P.S. хм, вообще интересно где может быть критична скорость выделения/освобождения памяти - может с дизайном не всё в порядке?...

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

new вызывает конструкторы для классов (а те вызыватют конструкторы своих частей и т.д.) => jump-ов и просто действий может быть много.

Если не ошибаюсь аллокация обычно делается через анонимный mmap и расширяется как и степ при pf-ах. Правда там обычно захватывают больше одной страницы а потом хитро распределяют.

Т.е. в большинстве случаев imho при alloc-е нет pf-ов, есть просто вызов стандартной библиотеки в том-же процессе. И разница не катастрофична(нету лишних syscall/pf).

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

вот интересно стало как определяется падение производительности в процентном соотношении кол-во syscall'ов/кол-во page fault'ов?

мне почему то кажется что большое кол-во page fault'ов хуже чем большое кол-во сисколов (хотя понятно что сисколы косвенно бьют и по другим вешам - кэшу например)...

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

> вот интересно стало как определяется падение производительности в процентном соотношении кол-во syscall'ов/кол-во page fault'ов?

не знаю, я про это не говорил.

> мне почему то кажется что большое кол-во page fault'ов хуже чем большое кол-во сисколов (хотя понятно что сисколы косвенно бьют и по другим вешам - кэшу например)...

imho примерно одинаково, главное переключение в ядро есть и возможно обращение к диску. Тут уж не до кэша. =)

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

ну если не ошибаюсь page fault не всегда означает доступ к диску (может просто SIGSEGV) - так что не факт что 50/50

испоганивание кеша и reschedule при выходе из сискола тоже счастья не добавляют (хотя по сравнению с доступом к диску это сущая ерунда)

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

... за исключением случаев когда нужна переносимость между компиляторами

локальные массивы переменной длины - есть в С99, но являются гнутым расширением для С++

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

может быть - писал по памяти, но смысл ИМХО передан верно.

Begemoth ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.