Как будто вы пытаетесь получить доступ к объекту, который является null
. Рассмотрим ниже пример:
TypeA objA;
. В это время вы только что объявили этот объект, но не инициализировали или не инициализировали. И всякий раз, когда вы пытаетесь получить доступ к каким-либо свойствам или методам в нем, он будет генерировать NullPointerException
, что имеет смысл.
См. Также этот пример:
String a = null;
System.out.println(a.toString()); // NullPointerException will be thrown
Ответ находится прямо на странице man
(по крайней мере, в Linux):
RETURN VALUE Функция alloca () возвращает указатель на начало выделенного пространства. Если распределение вызывает переполнение стека, поведение программы не определено.
blockquote>Нельзя сказать, что он никогда не должен использоваться. Один из проектов OSS, над которыми я работаю, широко использует его, и до тех пор, пока вы не злоупотребляете им (
alloca
«огромные ценности»), все в порядке. Как только вы пройдете отметку «несколько сотен байт», пришло время использоватьmalloc
и друзей. Вы все равно можете получить отказ в распределении, но по крайней мере у вас будет некоторое указание на отказ, а не просто выдувание стека.
Как отмечалось в этой публикации в группе новостей , есть несколько причин, по которым использование alloca
можно считать трудным и опасным:
alloca
. alloca
, поэтому переносимость не гарантируется даже между компиляторами, которые его поддерживают. alloca()
, требуются отдельные регистры для хранения указателя стека и указателя кадра. На процессорах x86 & gt; = 386 указатель стека ESP
может использоваться для обоих, освобождая EBP
- если не используется alloca()
.
– j_random_hacker
27 June 2010 в 14:30
f(42, alloca(10), 43);
может потерпеть крах из-за возможности того, что указатель стека будет отрегулирован на alloca()
после i> по меньшей мере одним из аргументы нажимаются на него.
– j_random_hacker
27 June 2010 в 14:38
Большинство ответов здесь в основном не совпадают с точкой: есть причина, по которой использование _alloca()
потенциально хуже, чем просто хранение больших объектов в стеке.
Основное различие между автоматическим хранилищем и _alloca()
заключается в том, что последний страдает от дополнительной (серьезной) проблемы: выделенный блок не контролируется компилятором , поэтому компилятор не может оптимизировать или перерабатывать его.
Сравнить:
while (condition) {
char buffer[0x100]; // Chill.
/* ... */
}
с:
while (condition) {
char* buffer = _alloca(0x100); // Bad!
/* ... */
}
Проблема с последним должна быть очевидной.
alloca
(да, я говорю VLA, потому что alloca
больше, чем просто создатель массивов статического размера)?
– Ruslan
29 April 2017 в 15:33
IMHO, alloca считается плохой практикой, потому что все боятся исчерпать ограничение размера стека.
Я многому научился, прочитав этот поток и некоторые другие ссылки:
Я использую alloca в основном для того, чтобы сделать мои простые файлы C компилируемыми на msvc и gcc без каких-либо изменений, C89 style, no # ifdef _MSC_VER и т. д.
Спасибо! Эта нить заставила меня зарегистрироваться на этом сайте:)
По-моему, alloca (), где доступно, следует использовать только ограниченным образом. Очень похоже на использование «goto», довольно много других разумных людей испытывают сильное отвращение не только к использованию, но и к существованию alloca ().
Для встроенного использования, где размер стека известен, и ограничения могут быть навязаны посредством соглашения и анализа по размеру распределения, и когда компилятор не может быть обновлен для поддержки C99 +, использование alloca () в порядке, и я, как известно, использовал его.
Когда доступно, VLA могут иметь некоторые преимущества перед alloca (): компилятор может генерировать контрольные лимиты стека, которые будут захватывать доступ к ограничениям при использовании доступа к стилю массива (я не знаю, компиляторы делают это, но это можно сделать), и анализ кода может определить, правильно ли ограничены выражения доступа к массиву. Обратите внимание, что в некоторых средах программирования, таких как автомобильная, медицинская техника и авионика, этот анализ необходимо проводить даже для массивов фиксированного размера, как автоматического (в стеке), так и статического распределения (глобального или локального).
В архитектурах, в которых хранятся как данные, так и обратные адреса / указатели кадров в стеке (из того, что я знаю, это все они), любая переменная, назначенная стеком, может быть опасной, поскольку адрес переменной может быть взят и непроверенный ввод значения могут допускать всевозможные ошибки.
Переносимость менее опасна во встроенном пространстве, однако это хороший аргумент против использования alloca () вне тщательно контролируемых обстоятельств.
Вне встроенного пространства я использовал alloca () в основном внутри функций ведения журнала и форматирования для эффективности и в нерекурсивном лексическом сканере, где временные структуры (выделенные с помощью alloca () создаются во время токенизации и классификации, тогда постоянный объект (выделен через malloc ()) до того, как функция вернется. Использование alloca () для небольших временных структур значительно сокращает фрагментацию, когда выделяется постоянный объект.
Одна проблема заключается в том, что она не является стандартной, хотя широко поддерживается. При прочих равных условиях я бы всегда использовал стандартную функцию, а не обычное расширение компилятора.
Я не думаю, что кто-то упомянул об этом: Использование функции alloca в функции будет препятствовать или отключать некоторые оптимизации, которые в противном случае могли бы применяться в функции, поскольку компилятор не может знать размер фрейма стека функции.
Например, общая оптимизация компиляторами C заключается в том, чтобы исключить использование указателя фрейма внутри функции, образы кадров сделаны вместо указателя стека; поэтому есть еще один регистр для общего использования. Но если alloca вызывается внутри функции, разница между sp и fp будет неизвестна для части функции, поэтому эта оптимизация не может быть выполнена.
Учитывая редкость ее использования и его теневой статус как стандартная функция, разработчики компилятора, возможно, отключили любую оптимизацию , которая могла бы вызывать проблемы с alloca, если бы потребовалось больше усилий, чтобы заставить ее работать с alloca.
Одна из самых запоминающихся ошибок, которые я имел, это сделать с встроенной функцией, которая использовала alloca
. Он отображался как переполнение стека (потому что он выделяется в стеке) в случайных точках исполнения программы.
В файле заголовка:
void DoSomething() {
wchar_t* pStr = alloca(100);
//......
}
В файле реализации:
void Process() {
for (i = 0; i < 1000000; i++) {
DoSomething();
}
}
Итак, что произошло, это функция DoSomething
для компилятора, и все распределения стека выполнялись внутри функции Process()
и, таким образом, выдували стек. В моей защите (и я не был тем, кто нашел этот вопрос, мне пришлось идти и кричать одному из старших разработчиков, когда я не мог это исправить), это было не прямо alloca
, это был один из Макросы преобразования строки ATL.
Итак, урок - не используйте alloca
в функциях, которые, по вашему мнению, могут быть встроены.
К сожалению, действительно удивительный alloca()
отсутствует из почти удивительного tcc. Gcc имеет alloca()
.
malloc()
, он возвращает недопустимый указатель на fail, который будет segfault на современных системах с MMU (и, надеюсь, перезапустить их без). Он хорошо работает с рекурсией. Вы можете использовать статические переменные для достижения чего-то подобного хвостовой рекурсии и использовать только несколько других, чтобы передавать информацию на каждую итерацию.
Если вы слишком сильно нажимаете, вы уверены в segfault (если у вас есть MMU).
Обратите внимание, что malloc()
больше не предлагает, поскольку возвращает NULL (который также будет segfault, если назначен), когда система не работает. То есть все, что вы можете сделать, это залог или просто попытаться назначить его любым способом.
Чтобы использовать malloc()
, я использую глобальные переменные и назначаю их NULL. Если указатель не равен NULL, я освобожу его, прежде чем использовать malloc()
.
Вы также можете использовать realloc()
в качестве общего случая, если хотите скопировать любые существующие данные. Вам нужно проверить указатель перед тем, как это сделать, если вы собираетесь копировать или конкатенировать после realloc()
.
alloca()
выделяет память, которая длится до конца функции. Это означает, что, по-видимому, нет простого, удобного перевода в VLA f() { char *p; if (c) { /* compute x */ p = alloca(x); } else { p = 0; } /* use p */ }
. Если вы считаете, что можно автоматически перевести использование alloca
в использование VLA, но для описания того, как это сделать, требуется больше, чем комментарий, я могу задать вопрос.
– Pascal Cuoq
24 March 2014 в 11:40
Все остальные ответы верны. Однако, если вещь, которую вы хотите выделить с помощью alloca()
, достаточно мала, я считаю, что это хорошая техника, которая быстрее и удобнее, чем использование malloc()
или иначе.
Другими словами, alloca( 0x00ffffff )
опасен и может вызвать переполнение, ровно столько же, сколько char hugeArray[ 0x00ffffff ];
. Будьте осторожны и разумны, и все будет хорошо.
Одна ошибка с alloca
заключается в том, что longjmp
перематывает ее назад.
То есть, если вы сохраняете контекст с setjmp
, тогда alloca
некоторое количество памяти, тогда longjmp
в контексте вы можете потерять память alloca
(без какого-либо уведомления). Указатель стека возвращается туда, где он был, и поэтому память больше не сохраняется; если вы вызываете функцию или выполняете другую alloca
, вы будете clobber оригинала alloca
.
Кстати, это обеспечивает правдоподобный механизм преднамеренного освобождения памяти, который был выделен с помощью alloca
.
Это нигде не документировано; конечно, описание ISO C setjmp
ничего не говорит о взаимодействиях с alloca
, так как не описывает такую функцию. Реализации, которые предоставляют alloca
, также не документируют это.
Фокус обычно заключается в том, что память alloca
связана с активацией функции , а не с каким-либо блоком ; что несколько вызовов alloca
просто захватывают больше памяти стека, которые все освобождаются при завершении функции. Не так; память фактически связана с контекстом процедуры. Когда контекст восстанавливается с помощью longjmp
, так же, как и предыдущее состояние alloca
.
Я столкнулся с этим, что я знаю.
alloca () хорош и эффективен ... но он также сильно нарушен.
В большинстве случаев вы можете заменить его, используя локальные переменные и размер мажоранты. Если он используется для больших объектов, их размещение в куче обычно является более безопасной идеей.
Если вам это действительно нужно, вы можете использовать VLA (нет vla на C ++, слишком плохо). Они намного лучше, чем alloca () относительно поведения и согласованности области. Как я вижу, VLA - это своего рода alloca (), сделанный правильно.
Конечно, локальная структура или массив с использованием мажоранты требуемого пространства все же лучше, и если у вас нет такого распределения кучи мажоранты с использованием простого malloc (), вероятно, разумно. Я не вижу здравого смысла, когда вам действительно нужно либо alloca (), либо VLA.
alloca
не создает имя, а только диапазон памяти, который имеет время жизни .
– curiousguy
27 October 2015 в 07:27
alloca
или malloc
или free
напрямую. Я говорю такие вещи, как {stack|heap}_alloc_{bytes,items,struct,varstruct}
и {stack|heap}_dealloc
. Таким образом, heap_dealloc
просто вызывает free
, а stack_dealloc
- нет-op. Таким образом, распределение стека может быть легко понижено до распределения кучи, и намерения также более ясны.
– Todd Lehman
1 April 2016 в 15:09
Функция alloca велика, и все скептики просто распространяют FUD.
void foo()
{
int x = 50000;
char array[x];
char *parray = (char *)alloca(x);
}
Массив и парсер являются ТОЧНО одинаковыми с ТОЧНО теми же рисками. Говорить одно лучше другого - это синтаксический выбор, а не технический.
Что касается выбора переменных стека против переменных кучи, существует много преимуществ для долгосрочных программ, использующих стек над кучей для переменных с время жизни. Вы избегаете фрагментации кучи, и вы можете избежать роста пространства процесса с неиспользуемым (непригодным) кучевым пространством. Вам не нужно его чистить. Вы можете контролировать распределение стека в процессе.
Почему это плохо?
Место, где alloca()
особенно опасно, чем malloc()
- ядро - ядро типичной операционной системы имеет фиксированное пространство стека, жестко закодированное в один из его заголовков; он не такой гибкий, как стек приложения. Выполнение вызова alloca()
с неоправданным размером может привести к сбою ядра. Некоторые компиляторы предупреждают об использовании alloca()
(и даже VLA, если на то пошло) при определенных параметрах, которые должны быть включены при компиляции кода ядра. Здесь лучше выделить память в куче, которая не фиксируется жестким диском, закодированный предел.
alloca()
не более опасен, чем int foo[bar];
, где bar
- некоторое произвольное целое число.
– Todd Lehman
25 August 2015 в 23:20
Старый вопрос, но никто не упомянул, что он должен быть заменен массивами переменной длины.
char arr[size];
вместо
char *arr=alloca(size);
Он находится в стандарте C99 и существует как расширение компилятора во многих компиляторах.
Много интересных ответов на этот «старый» вопрос, даже некоторые относительно новые ответы, но я не нашел никаких упоминаний об этом ....
При правильном использовании и с осторожностью , последовательное использование
blockquote>alloca()
(возможно, всего прикладного) для обработки небольших распределений переменной длины (или VLAs C99, если доступно) может привести к снижению общего роста стека, чем эквивалентная реализация в противном случае, используя большие локальные массивы фиксированной длины. Поэтомуalloca()
может быть полезен для вашего стека , если вы его тщательно используете.Я нашел эту цитату .... Хорошо, я сделал эту цитату , Но на самом деле, подумайте об этом ....
@j_random_hacker очень прав в своих комментариях по другим ответам: Избегание использования
alloca()
в пользу больших локальных массивов не делает вашу программу более безопасной из стека переполнения (если ваш компилятор не является достаточно старым, чтобы разрешить встраивание функций, которые используютalloca()
, в этом случае вы должны обновить или если вы не используетеalloca()
внутренние циклы, в этом случае вам не нужно использоватьalloca()
внутри циклов ).Я работал над средами настольных компьютеров и серверов и встроенными системами. Многие встроенные системы вообще не используют кучу (они даже не ссылаются на поддержку) по причинам, которые включают в себя восприятие того, что динамически распределенная память является злой из-за риска утечек памяти в приложении, которое никогда когда-либо перезагружается в течение многих лет за раз, или более разумное обоснование того, что динамическая память опасна, потому что неизвестно, что приложение никогда не будет фрагментировать свою кучу до уровня исчерпания ложной памяти. Таким образом, встроенные программисты остались с несколькими альтернативами.
alloca()
(или VLAs) может быть правильным инструментом для задания.Я видел время & amp; время, когда программист создает буфер, распределенный по стекам, «достаточно большой для обработки любого возможного случая». В глубоко вложенном дереве вызовов повторное использование этого шаблона (anti-?) Приводит к преувеличенному использованию стека. (Представьте, что дерево вызовов 20 уровней глубоко, где на каждом уровне по разным причинам функция слепо перераспределяет буфер размером 1024 байта «только для того, чтобы быть в безопасности», когда обычно он будет использовать только 16 или меньше из них, и только в очень редкие случаи могут использовать больше.) Альтернативой является использование
alloca()
или VLA и выделение только столько места стека, сколько требуется вашей функции, чтобы избежать излишнего обременения стека. Надеемся, что когда одна функция в дереве вызовов нуждается в распределении большего, чем обычно, другие в дереве вызовов все еще используют свои обычные небольшие распределения, а общее использование стека приложений значительно меньше, чем если бы каждая функция вслепую чрезмерно распределяла локальный буфер .Но если вы решите использовать
alloca()
...Основываясь на других ответах на этой странице, кажется, что VLA должны быть безопасными (они не объединяют распределения стека если вы вызываете из цикла), но если вы используете
alloca()
, будьте осторожны, чтобы не использовать его внутри цикла, и make sure ваша функция не может быть встроена, если есть вероятность, что она может быть вызвана в цикле другой функции.
alloca()
истинно, но то же самое можно сказать и о утечках памяти с помощью malloc()
(почему бы не использовать GC тогда? Можно утверждать). alloca()
при использовании с осторожностью может быть действительно полезно уменьшить размер стека.
– Felipe Tonello
2 February 2017 в 16:44
Вот почему:
char x;
char *y=malloc(1);
char *z=alloca(&x-y);
*z = 1;
Не то, чтобы кто-нибудь написал этот код, но аргумент размера, который вы переходите на alloca
, почти наверняка исходит из какого-то ввода, который мог бы злонамеренно получите свою программу в alloca
что-то огромное. В конце концов, если размер не основан на вводе или не имеет возможности быть большим, почему бы вам просто не объявить небольшой локальный буфер фиксированного размера?
Практически весь код, используя alloca
и / или C99 vlas имеют серьезные ошибки, которые приведут к сбоям (если вам повезет) или к компрометации привилегий (если вам не повезло).
alloca
. Вы сказали, что почти весь код, который использует его, имеет ошибку, но я планировал его использовать, я обычно проигнорировал бы такой иск , но исходящий от вас я не буду. Я пишу виртуальную машину, и я бы хотел выделить переменные, которые не выходят из функции в стеке, а не динамически из-за огромного ускорения. есть альтернативный подход, который имеет те же характеристики производительности? Я знаю, что могу приблизиться к пулам памяти, но это все еще не так дешево. Что бы вы сделали?
– GManNickG
26 May 2011 в 03:33
*0 = 9;
УДИВИТЕЛЬНО !!! Думаю, я никогда не должен использовать указатели (или, по крайней мере, разыгрывать их). Эрр, подождите. Я могу проверить, является ли оно нулевым. Хм. Думаю, я также могу проверить размер памяти, которую я хочу выделить через alloca
. Странный человек. Weird.
– Thomas Eding
16 November 2011 в 23:41
*0=9;
недействительно C. Что касается проверки размера, который вы переходите на alloca
, проверьте его на что? Невозможно узнать предел, и если вы собираетесь протестировать его с небольшим фиксированным известным безопасным размером (например, 8k), вы можете просто использовать массив фиксированного размера в стеке.
– R..
17 November 2011 в 05:07
small_constant * log(user_input)
, то у нас, вероятно, будет достаточно памяти.
– j_random_hacker
16 April 2012 в 04:00
Процессы имеют ограниченное количество пространства стека - намного меньше, чем объем памяти, доступный для malloc()
.
Используя alloca()
, вы значительно увеличите свои шансы получить ошибку переполнения стека (если вам повезет, или необъяснимый сбой, если вы этого не сделали).
Если вы случайно напишете за пределами блока, выделенного с помощью alloca
(например, из-за переполнения буфера), вы перезапишите адрес возврата вашей функции, потому что он находится выше "в стеке, т. е. после вашего выделенного блока.
Следствием этого является двоякое:
Напротив, если вы пишете за пределами блок на куче, который вы «просто» получаете от кучи. Программа, вероятно, прекратится неожиданно, но будет правильно раскручивать стек, тем самым уменьшая вероятность выполнения вредоносного кода.
alloca
.
– phonetagger
31 March 2016 в 21:15
alloca
по сравнению с malloc
(таким образом, буфер не фиксированного размера в стеке).
– rustyx
1 April 2016 в 11:29
Все уже указали на большую вещь, которая является потенциальным неопределенным поведением из переполнения стека, но я должен упомянуть, что в среде Windows есть отличный механизм, чтобы поймать это, используя структурированные исключения (SEH) и защитные страницы. Поскольку стек растет только по мере необходимости, эти страницы защиты находятся в областях, которые нераспределены. Если вы выделяете в них (путем переполнения стека), генерируется исключение.
Вы можете поймать это исключение SEH и вызвать _resetstkoflw, чтобы сбросить стек и продолжить свой веселый путь. Это не идеально, но это еще один механизм, по крайней мере, знать, что что-то пошло не так, когда материал попадает в вентилятор. * nix может иметь что-то подобное, о котором я не знаю.
Я рекомендую ограничить максимальный размер выделения, обернув alloca и отслеживая его внутренне. Если бы вы были очень хардкорны, вы могли бы бросить часовые прицелы в верхней части своей функции, чтобы отслеживать любые распределения alloca в области функций и здравомыслия, проверяя это на максимальную сумму, допустимую для вашего проекта.
Кроме того, в дополнение к недопущению утечек памяти alloca не вызывает фрагментации памяти, что очень важно. Я не думаю, что alloca - это плохая практика, если вы используете ее разумно, что в принципе верно для всего. : -)
Не очень красиво, но если производительность действительно имеет значение, вы можете предварительно выделить некоторое пространство в стеке.
Если вы уже сейчас используете максимальный размер блока памяти, и вы хотите продолжать проверку переполнения, вы можете сделать что-то вроде:
void f()
{
char array_on_stack[ MAX_BYTES_TO_ALLOCATE ];
SomeType *p = (SomeType *)array;
(...)
}
still alloca use не рекомендуется, почему?
Я не воспринимаю такой консенсус. Множество сильных профи; несколько минусов:
C99 предоставляет массивы переменной длины, которые часто использовались бы предпочтительнее, поскольку нотация более совместима с массивами с фиксированной длиной и интуитивным общим , что многие системы имеют меньше общая память / адресное пространство, доступное для стека, чем для кучи, что делает программу немного более восприимчивой к исчерпанию памяти (через переполнение стека): это можно рассматривать как хорошее или плохое - одна из причин стек автоматически не развивается так, как это делает куча, чтобы предотвратить недоступность программ контроля недействительности для всего компьютера при использовании в более локальной области (например, while
илиfor
) или в нескольких областях, память накапливается на каждую итерацию / область действия и не освобождается до выхода функции: это контрастирует с нормальными переменными, определенными в области структуры управления (например,for {int i = 0; i < 2; ++i) { X }
будет накапливатьсяalloca
запрошенную в X, но память для массива фиксированного размера будет переработана на итерацию).современные компиляторы обычно не выполняют функции inline
, которые вызываютalloca
, но если вы их заставляете, тоalloca
произойдет в контексте вызывающих абонентов (т. стек не будет выпущен до тех пор, пока вызывающий абонент не вернется)давным-давно alloca
перешел из непереносимой функции / взлома в стандартизованное расширение, но некоторое негативное восприятие может сохранятьсявремя жизни привязано к области видимости функции, которая может или не подходит программисту лучше, чем явный контроль malloc
, который должен использовать malloc
, побуждает думать об освобождении - если это управляемый через функцию обертки (например,WonderfulObject_DestructorFree(ptr)
), тогда функция предоставляет точку для операций очистки операций (например, закрытие дескрипторов файлов, освобождение внутренних указателей или выполнение некоторых протоколов) без явных изменений кода клиента: иногда это хорошая модель для последовательно внедряются в этот псевдо-OO-стиль программирования, естественно хотеть что-то вродеWonderfulObject* p = WonderfulObject_AllocConstructor();
- это возможно, когда «конструктор» - это функция, возвращающая памятьmalloc
(поскольку память остается выделенной после того, как функция возвращает значение для сохранения вp
), но не при использовании «конструктора» salloca
макро-версияWonderfulObject_AllocConstructor
могла бы достичь этого, но «макросы злы» в том, что они могут конфликтовать друг с другом и не-макрокодом и создавать непреднамеренные замены и, следовательно, трудно диагностировать недостающие проблемыfree
операции могут быть обнаружены ValGrind, Purify и т. д., но отсутствующие вызовы «деструктор» не всегда могут быть обнаружены вообще - одно очень незначительное преимущество в плане обеспечения предполагаемого использования; в некоторых реализацияхalloca()
(например, GCC) используется встроенный макрос дляalloca()
, поэтому замена временной библиотеки памяти для использования памяти не возможна, как это делается дляmalloc
/realloc
/free
( например, электрический забор)некоторые реализации имеют тонкие проблемы: например, из справочной системы Linux: во многих системах alloca () не может использоваться внутри списка аргументов вызова функции, поскольку пространство стека, зарезервированное alloca () появится в стеке в середине пространства для аргументов функции. Я знаю, что этот вопрос отмечен C, но как программист на C ++ я думал, что буду использовать C ++ чтобы проиллюстрировать потенциальную полезность
alloca
: приведенный ниже код (и здесь в ideone ) создает векторное отслеживание полиморфных типов разного размера, которые выделены в стек (с привязкой времени жизни к возврату функции), а не с распределением кучи .#include <alloca.h> #include <iostream> #include <vector> struct Base { virtual ~Base() { } virtual int to_int() const = 0; }; struct Integer : Base { Integer(int n) : n_(n) { } int to_int() const { return n_; } int n_; }; struct Double : Base { Double(double n) : n_(n) { } int to_int() const { return -n_; } double n_; }; inline Base* factory(double d) __attribute__((always_inline)); inline Base* factory(double d) { if ((double)(int)d != d) return new (alloca(sizeof(Double))) Double(d); else return new (alloca(sizeof(Integer))) Integer(d); } int main() { std::vector<Base*> numbers; numbers.push_back(factory(29.3)); numbers.push_back(factory(29)); numbers.push_back(factory(7.1)); numbers.push_back(factory(2)); numbers.push_back(factory(231.0)); for (std::vector<Base*>::const_iterator i = numbers.begin(); i != numbers.end(); ++i) { std::cout << *i << ' ' << (*i)->to_int() << '\n'; (*i)->~Base(); // optionally / else Undefined Behaviour iff the // program depends on side effects of destructor } }
На самом деле alloca не гарантирует использование стека. В самом деле реализация gcc-2.95 alloca выделяет память из кучи, используя сам malloc. Кроме того, эта реализация глючит, это может привести к утечке памяти и к неожиданному поведению, если вы вызовете ее внутри блока с дальнейшим использованием goto. Нет, чтобы сказать, что вы никогда не должны использовать его, но иногда alloca приводит к большему количеству накладных расходов, чем он отходит от.
alloca()
, не испытывают такого же страха перед локальными массивами или рекурсией (на самом деле многие люди, которые будут кричатьalloca()
, будут хвалить рекурсию, потому что он «выглядит элегантно»). Я согласен с советом Шона (& quot; alloca () отлично подходит для небольших распределений & quot;), но я не согласен с мнением, что рамки alloca () как однозначно злые среди 3 - они одинаково опасны! – j_random_hacker 2 August 2010 в 06:33