Что такое alloca я думаю объяснять никому не надо — функция выделения памяти на стеке.
Плюсы:
— быстро
— не нужно освобождать
Грабли:
— много не выделишь
—
приводит к проблемам. Дело в том что большинство компиляторов в этом случа не воспринимают тело цикла как scope и в зависимости от количества итераций стек может кончиться а может и нет
— неуловимый баг
CComBSTR bs = ........;
CString s = ...........;
for(.......)
{
if (bs == s)
{
......
break;
}
}
Казалось бы ничто не предвещает беды, но все-таки этот код МОЖЕТ содержать баг.
bs == s вызывает bool CComBSTR::operator==(LPCSTR pszSrc) const
так вот при некоторых оптимизациях (мне не удалось повторить условия в тестовых условиях но в реальном проекте такое происходит) вызов bool CComBSTR::operator== инлайнится. Это довольно мерзкий баг потому что проявляется он ТОЛЬКО в release на большом количестве итераций цикла и может произвольно появляться и исчезать в зависимости от мелких изменений в коде.
Здравствуйте, Bell, Вы писали:
B>Это про оператор сравнения? Тогда при чем тут alloca? Плохо, конечно, что в документации к этому оператору не указана это особенность (или указана?) но это — , ИМХО, дефект реализации/документации оператора, но никак ни средсва реализации.
Это дефект компилятора, который инлайнит функцию, содержащую alloca(), и не вставляет туда код по восстановлению стека.
Здравствуйте, rm822, Вы писали:
R>приводит к проблемам. Дело в том что большинство компиляторов в этом случа не воспринимают тело цикла как scope и в зависимости от количества итераций стек может кончиться а может и нет
RTFM man alloca:
DESCRIPTION
The alloca() function allocates size bytes of space in the stack frame of
the caller. This temporary space is automatically freed on return.
Память освобождается при выходе их функции, не при выходе из скопа. Так что тут ты просто некорректно используешь.
То, что размер надо проверять, это само сабой — произвольный размер туда передавать нельзя.
R>так вот при некоторых оптимизациях (мне не удалось повторить условия в тестовых условиях но в реальном проекте такое происходит) вызов bool CComBSTR::operator== R>инлайнится. Это довольно мерзкий баг потому что проявляется он ТОЛЬКО в release на большом количестве итераций цикла и может произвольно появляться и исчезать в зависимости от мелких изменений в коде.
Вот это, конечно, неприятно, если это действительно так...
R>>>Вот это, конечно, неприятно, если это действительно так...
К>>Здесь, формально, выход из функции есть, а реально его нет (оптимизатор выбросил ненужный, по его мнению, код пролога-эпилога).
R>В вот здесь
#include <atlconv.h>
struct C
{
__inline char *Convert(LPCWSTR sString)
{
USES_CONVERSION;
char *c = W2A(sString);
_strupr(c);
// unusable, coz surely should be freed; return c;
}
};
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
C c;
for(int i = 0; i < argc * 100; ++i)
{
void *pEsp;
__asm mov [pEsp], esp;
printf("before: %p\n", pEsp);
c.Convert(L"test string");
__asm mov [pEsp], esp;
printf("after: %p\n", pEsp);
}
return 0;
}
Достаточно попробовать в дебаге и в релизе. Хотя, судя по листингу, VC честно пытается восстановить стек-фрейм (сохраняет esp и затем его восстанавливает), но безуспешно. Да, измерения можно расставлять по вкусу — как в теле цикла, так и вне — это сути не меняет.
Здравствуйте, Bell, Вы писали:
B>Любым молотком можно ударить себя по пальцам, но это не означает, что нужно немедленно прекратить использовать молоток.
В данном случае ты не управляешь молотком, сначала он тебя ударит по пальцам а потом и по башке может садануть.
Здравствуйте, remark, Вы писали:
R>Память освобождается при выходе их функции, не при выходе из скопа. Так что тут ты просто некорректно используешь. R>То, что размер надо проверять, это само сабой — произвольный размер туда передавать нельзя.
R>>так вот при некоторых оптимизациях (мне не удалось повторить условия в тестовых условиях но в реальном проекте такое происходит) вызов bool CComBSTR::operator== R>>инлайнится. Это довольно мерзкий баг потому что проявляется он ТОЛЬКО в release на большом количестве итераций цикла и может произвольно появляться и исчезать в зависимости от мелких изменений в коде.
R>Вот это, конечно, неприятно, если это действительно так...
Здесь, формально, выход из функции есть, а реально его нет (оптимизатор выбросил ненужный, по его мнению, код пролога-эпилога).
Здравствуйте, red_dragon, Вы писали:
_>Здравствуйте, remark, Вы писали:
R>>Основная проблема в том, что нельзя угадать как компилятор заинлайнит функции.
_>Поэтому не стоит использовать такие низкоуровневые средства управляния памятью, как alloc в inline-функциях
Ты путаешь понятия: inline-функция, которая объявлена как inline (явно или неявно) и inline-функция, которая реально заинлайнена компилятором при генерации кода.
Здравствуйте, remark, Вы писали:
R>Ты путаешь понятия: inline-функция, которая объявлена как inline (явно или неявно) и inline-функция, которая реально заинлайнена компилятором при генерации кода.
Разве? А что компилятор может инлайнить ф-ции, которые никаким образом не объявлены инлайн? По-моему даже при самой максимальной оптимизации, компиляторы таким не занимаются. Или я ошибаюсь
Здравствуйте, Bell, Вы писали:
B>Здравствуйте, rm822, Вы писали:
B>Любым молотком можно ударить себя по пальцам, но это не означает, что нужно немедленно прекратить использовать молоток.
чтобы молоток не ударил, требовать использовать только в неинлановых функциях и чтобы не был в циклах.
а вообще, функция из эпохи, когда не было инлайнов
Здравствуйте, rm822, Вы писали:
R>Здравствуйте, Bell, Вы писали:
B>>Любым молотком можно ударить себя по пальцам, но это не означает, что нужно немедленно прекратить использовать молоток. R>В данном случае ты не управляешь молотком, сначала он тебя ударит по пальцам а потом и по башке может садануть.
Это про оператор сравнения? Тогда при чем тут alloca? Плохо, конечно, что в документации к этому оператору не указана это особенность (или указана?) но это — , ИМХО, дефект реализации/документации оператора, но никак ни средсва реализации.
Здравствуйте, rm822, Вы писали:
R>приводит к проблемам. Дело в том что большинство компиляторов в этом случа не воспринимают тело цикла как scope
R> return wcscmp(m_str, A2W(pszSrc)) == 0; //A2W — cодержит alloca
В MSDN не прописано, но
1 — скопе в данном случае это всегда должно быть тело функции
2 — fun(aloca()) недопустимо, можно ptr=aloca(); fun(ptr)
Совсем непонятно что такое A2W? — где содержится результат? Пожоже у Вас какойто макрос, со слижком вольным обращением со стеком.
Здравствуйте, Programador, Вы писали:
P>Здравствуйте, rm822, Вы писали:
R>>приводит к проблемам. Дело в том что большинство компиляторов в этом случа не воспринимают тело цикла как scope
R>> return wcscmp(m_str, A2W(pszSrc)) == 0; //A2W — cодержит alloca
P>В MSDN не прописано, но P>1 — скопе в данном случае это всегда должно быть тело функции P>2 — fun(aloca()) недопустимо, можно ptr=aloca(); fun(ptr)
P>Совсем непонятно что такое A2W? — где содержится результат? Пожоже у Вас какойто макрос, со слижком вольным обращением со стеком.
A2W и W2A это два макроса, вроде из ATL а может и WTL преобразубт анси в вайдчар и вайдчар в анси соответсвенно
Спасибо.
Здравствуйте, Programador, Вы писали: P>Совсем непонятно что такое A2W? — где содержится результат? Пожоже у Вас какойто макрос, со слижком вольным обращением со стеком.
Я то тут при чем? Не у меня а у MFC\ATL — все претензии к M$.
Здравствуйте, rm822, Вы писали:
R>так вот при некоторых оптимизациях (мне не удалось повторить условия в тестовых условиях но в реальном проекте такое происходит) вызов bool CComBSTR::operator== R>инлайнится.
А где тело ператора — прямо в классе?
Здравствуйте, Programador, Вы писали:
Посмотрел A2W. МС нарушает fun(aloca()). Вообще смысл этого ограничения в том что стек меняется в процессе проталкивания. Правда там алока первым параметрои идет, наверно поэтому прокатывает.
Так где оператор описан?
Здравствуйте, rm822, Вы писали:
R>>Вот это, конечно, неприятно, если это действительно так... R>Reproduced! R>здесь
R>характерно что на VC6 чтобы упасть ему нужен Inline R>а на VS2005 этот инлайн можно смело убрать и он все равно падает.
Да — действительно ::MessageBox(0,"shit","shit",0);
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
R>>>так вот при некоторых оптимизациях (мне не удалось повторить условия в тестовых условиях но в реальном проекте такое происходит) вызов bool CComBSTR::operator== R>>>инлайнится. Это довольно мерзкий баг потому что проявляется он ТОЛЬКО в release на большом количестве итераций цикла и может произвольно появляться и исчезать в зависимости от мелких изменений в коде.
R>>Вот это, конечно, неприятно, если это действительно так...
К>Здесь, формально, выход из функции есть, а реально его нет (оптимизатор выбросил ненужный, по его мнению, код пролога-эпилога).
Он действительно так делает или это гипотеза?
И vc6 и vc8 генерируют в такой ситуации некорректный код? а vc71?
Да так самое интересное я и не разяснил. Фунуция не инлайн. Вроде 1 мег стек по умолчанию? Просто такое подозрение, что они как-то попытались хитро лечить фичу с инлайном и в результате получили баг
Здравствуйте, Sni4ok, Вы писали:
_>>чтобы небыло багов, пользуемся new, delete
S>интересно посмотреть на эксепшин сэйф код с активным использованием delete'а
Я полагаю, подразумвается использование delete в деструкторах смартпоинтеров?
И вообще, насколько я понял, new и delete были упомянуты в смысле альтернативы alloca, а не как панацея от всех бед.
P. S. Иногда alloca рулит.
До последнего не верил в пирамиду Лебедева.
Re: Бойтесь alloca
От:
Аноним
Дата:
27.03.07 09:31
Оценка:
R>Что такое alloca я думаю объяснять никому не надо — функция выделения памяти на стеке.
Здравствуйте, Programador, Вы писали:
P>Да так самое интересное я и не разяснил. Фунуция не инлайн. Вроде 1 мег стек по умолчанию? Просто такое подозрение, что они как-то попытались хитро лечить фичу с инлайном и в результате получили баг
Ну а чего ты удивляешься, если ты используешь строку в памяти, которая уже освобождена?
Здравствуйте, Programador, Вы писали:
P>Здравствуйте, remark, Вы писали:
R>>Ну а чего ты удивляешься, если ты используешь строку в памяти, которая уже освобождена?
P>Где ??? Код от rm822 http://konsuello.mine.nu/stackoverflow/stackoverflow.zipсовершенно легальный
//inline
char * foo(int i)
{
char* c=(char*)alloca(i+1);
*c =0;
return c; // вот здесь память освобождается
//printf(c);
}
Здравствуйте, red_dragon, Вы писали:
_>Здравствуйте, Programador, Вы писали:
P>>Здравствуйте, remark, Вы писали:
R>>>Ну а чего ты удивляешься, если ты используешь строку в памяти, которая уже освобождена?
P>>Где ??? Код от rm822 http://konsuello.mine.nu/stackoverflow/stackoverflow.zipсовершенно легальный
_>//inline _>char * foo(int i) _>{ _> char* c=(char*)alloca(i+1); _> *c =0; _> return c; // вот здесь память освобождается _> //printf(c); _>}
А используется то где??? Чем этод код нелегальный?
Здравствуйте, Programador, Вы писали:
P>А используется то где??? Чем этод код нелегальный?
char* c = foo(i);
if (bs == c) // 1-ое c-указывает на область памяти, которой возможно уже не существует,break; // и возможно находится в другом сегменте
2-ое:
при резервировании большого кол-ва памяти при помощи alloca возможно:
— stack overflow
— segmentation failure
Здравствуйте, Programador, Вы писали:
P>Здравствуйте, remark, Вы писали:
R>>Здесь выполняется bool CComBSTR::operator == (LPCSTR pszSrc) const, который читает переданную память как strz
P>Да тип не посмотрел, с char* работает
Короче мне так ничо и не понятно — есть ошибка в компиляторе или нет
Если у кого чо падает — привидите плз ассемблерный код — где в функции sp не возвращается в зад
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Programador, Вы писали:
P>>Здравствуйте, remark, Вы писали:
R>>>Здесь выполняется bool CComBSTR::operator == (LPCSTR pszSrc) const, который читает переданную память как strz
P>>Да тип не посмотрел, с char* работает
R>Короче мне так ничо и не понятно — есть ошибка в компиляторе или нет R>Если у кого чо падает — привидите плз ассемблерный код — где в функции sp не возвращается в зад
R>
Все работает — просто мне показалось , что bs == c сравнение указателей. Код ассемблерный кстати весьма кудрявый в восьмерке
Здравствуйте, red_dragon, Вы писали:
_> при резервировании большого кол-ва памяти при помощи alloca возможно: _> — stack overflow
А при new возможен std::bad_alloc
_> — segmentation failure
Не в Виндовсе, там плоская модель памяти.
People who are more than casually interested in computers should have at least some idea of what the underlying hardware is like. Otherwise the programs they write will be pretty weird (c) D.Knuth
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, gear nuke, Вы писали:
_>>> — segmentation failure
GN>>Не в Виндовсе, там плоская модель памяти.
ДД>В линуксе тоже плоская модель памяти, а segmentation fault есть В винде он просто "access violation" чаще называется.
Правильнее сказать — в линуксе тоже есть access violation, просто он чаще называется segmentation fault
Ну что взять с неграмотных людей
Здравствуйте, rm822, Вы писали:
R>>Вот это, конечно, неприятно, если это действительно так... R>Reproduced! R>здесь
R>характерно что на VC6 чтобы упасть ему нужен Inline R>а на VS2005 этот инлайн можно смело убрать и он все равно падает.
Здравствуйте, Кодт, Вы писали:
R>>Вот это, конечно, неприятно, если это действительно так...
К>Здесь, формально, выход из функции есть, а реально его нет (оптимизатор выбросил ненужный, по его мнению, код пролога-эпилога).
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, remark, Вы писали:
R>>Правильнее сказать — в линуксе тоже есть access violation, просто он чаще называется segmentation fault
ДД> ДД>Когда segmentation fault появился, виндовс еще в проекте не было. См. здесь, например.
В смысле?
В любом случае не может быть segmentation fault, если сегментация памяти не используется. И в win и в linux это paging fault.
Называть paging fault — access violation'ом законно, т.к. и paging fault и segmentation fault — ошибки зашиты памяти.
А вот называть paging fault — segmentation fault'ом по ламерски
В смысле, что термин "segmentation fault" появился еще в unix'е .
R>В любом случае не может быть segmentation fault, если сегментация памяти не используется. И в win и в linux это paging fault.
Не привязывайтесь к архитектуре. Это в x86 есть исключение "Page fault", есть "Segment not present", а еще, кстати, есть "General Protection fault".
А в общем случае "segmentation fault" — это просто ситуация, термин "сегмент" ведь не обязательно означает сегмент в модели адресации памяти.
R>Называть paging fault — access violation'ом законно, т.к. и paging fault и segmentation fault — ошибки зашиты памяти.
Еще раз. Ситуация "segmentation fault" возникает, когда программа обращается к памяти неприемлимым для нее способом: пишет в защищенную от записи область, читает недоступный участок и т.д. Каким образом память защищена — на уровне сегментов, страниц или еще как — это не важно. А уже на разных архитектурах эта ситуация приводит к разным последствиям: в unix-like это посылка сигнала SIGSEGV, в windows — исключение STATUS_ACCESS_VIOLATION.
R>А вот называть paging fault — segmentation fault'ом по ламерски
Миллионы разработчиков с Вами не согласны
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
ДД>Еще раз. Ситуация "segmentation fault" возникает, когда программа обращается к памяти неприемлимым для нее способом: пишет в защищенную от записи область, читает недоступный участок и т.д. Каким образом память защищена — на уровне сегментов, страниц или еще как — это не важно. А уже на разных архитектурах эта ситуация приводит к разным последствиям: в unix-like это посылка сигнала SIGSEGV, в windows — исключение STATUS_ACCESS_VIOLATION.
Вот видишь как длинно приходится объяснять значение термина из-за плохо выбранного названия. Приходится говорить, что ошибка сегментации на самом деле может быть вызвана ошибкой пейджинга...
В windows из-за хорошо подобранного названия всё получается просто: ACCESS_VIOLATION — ошибка зашиты памяти.
Здравствуйте, Andrew S, Вы писали:
AS>Правда в том, что не работает. AS>Достаточно попробовать в дебаге и в релизе. Хотя, судя по листингу, VC честно пытается восстановить стек-фрейм (сохраняет esp и затем его восстанавливает), но безуспешно. Да, измерения можно расставлять по вкусу — как в теле цикла, так и вне — это сути не меняет.
Наконец понял
Правда без собственных тестов не обошлось. Пришлось заменить __inline на __forceinline, т.к. иначе всё работало и под релизом...
Мой вывод такой:
Вот описание функции из MSDN:
_alloca allocates size bytes from the program stack. The allocated space is automatically freed when the calling function exits (not when the allocation merely passes out of scope)
А фактически получается, что работает так:
_alloca allocates size bytes from the program stack. The allocated space is automatically freed when the first non-inlined calling function exits (not when the calling function exits and not when the allocation merely passes out of scope)
Основная проблема в том, что нельзя угадать как компилятор заинлайнит функции.
Частично заткнуть проблему можно добавляя __declspec(noinline) к функциям, использующим alloca. Понятно, что это можно забыть или не иметь доступ к коду.
Либо можно использовать свои буферы на стеке или глобальные. Тут минус, что неэкономно будет расходоваться стековое пространство, т.к. буфер придётся делать "максимального" размера.
Здравствуйте, remark, Вы писали:
R>Здравствуйте, Andrew S, Вы писали:
AS>>Правда в том, что не работает. AS>>Достаточно попробовать в дебаге и в релизе. Хотя, судя по листингу, VC честно пытается восстановить стек-фрейм (сохраняет esp и затем его восстанавливает), но безуспешно. Да, измерения можно расставлять по вкусу — как в теле цикла, так и вне — это сути не меняет.
R>Наконец понял R>Правда без собственных тестов не обошлось. Пришлось заменить __inline на __forceinline, т.к. иначе всё работало и под релизом...
Я проверял под msvc71. Но эти @#$%^ уже не дают регистрировать баги на msvc71 только на msvc2005/2005sp1/Orcas — вот @#$#%, поддержка 2003 что ли закончилась?
На msvc2005/2005sp1 такая же фигня или поправили?
R>
Здравствуйте, ДимДимыч, Вы писали:
R>>В windows из-за хорошо подобранного названия всё получается просто: ACCESS_VIOLATION — ошибка зашиты памяти. ДД>Если быть точным, то "нарушение доступа". Хорошо, что PERMISSION_DENIED не назвали
Это ты про UNIX-like?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, red_dragon, Вы писали:
_>Здравствуйте, remark, Вы писали:
R>>Ты путаешь понятия: inline-функция, которая объявлена как inline (явно или неявно) и inline-функция, которая реально заинлайнена компилятором при генерации кода.
_>Разве? А что компилятор может инлайнить ф-ции, которые никаким образом не объявлены инлайн? По-моему даже при самой максимальной оптимизации, компиляторы таким не занимаются. Или я ошибаюсь
Сейчас фактически на современных компиляторах эти два множества никак не связаны. Т.е. может инлайнится то, что не объялено инлайн, может не инлайнится то, что объявлено.
Более того, может инлайнится даже то, что вынесено в отдельную единицу трансляции.
Частично решают проблему такие вещи как __forceinline, __declspec(noinline). Но я точно знаю, что и __forceinline может быть не заинлайнен — при этом выдаётся варнинг. Но тут проблема — тебе уже надо не просто "не стоит использовать такие низкоуровневые средства управляния памятью, как alloc в inline-функциях", а найти все такие функции в своём коде, найти все такие функции в системных и сторонних библиотеках и пометить их как __declspec(noinline) и надеятся, что так и будет. И потом на протяжении всей жизни следить за изменениями в в системных и сторонних библиотеках на предмет появления новых функций.
Здравствуйте, red_dragon, Вы писали:
_>Разве? А что компилятор может инлайнить ф-ции, которые никаким образом не объявлены инлайн? По-моему даже при самой максимальной оптимизации, компиляторы таким не занимаются. Или я ошибаюсь
Ошибаешься.
Уже довольно давно компиляторы пытаются использовать информацию из определения функции, если оно доступно в точке вызова.
Так что слово inline уже давно довольно влияет только на ODR
А теперь компиляторы уже умеют использовать и определениея, которые в точке вызова не видны
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, remark, Вы писали:
R>Частично заткнуть проблему можно добавляя __declspec(noinline) к функциям, использующим alloca. Понятно, что это можно забыть или не иметь доступ к коду. R>Либо можно использовать свои буферы на стеке или глобальные. Тут минус, что неэкономно будет расходоваться стековое пространство, т.к. буфер придётся делать "максимального" размера.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
R>>>В windows из-за хорошо подобранного названия всё получается просто: ACCESS_VIOLATION — ошибка зашиты памяти. ДД>>Если быть точным, то "нарушение доступа". Хорошо, что PERMISSION_DENIED не назвали E>Это ты про UNIX-like?
Да про все понемножку
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
говорят, что ничего не падает... очная ставка!
Там говорят отчасти правду, позор на мои седины.
На 2005.sp1 оно работает правильно, это у меня ошибка в коде
Там компилер присутствие alloca воспринимает весьма однозначно.
1. функция не будет заинлайнена
2. функция не будет заинлайнена даже если вызов alloca будет выброшен в процессе оптимизации
3. в функции будет сгенерирован пролог и эпилог проверяющий состояние стека.
про VC6 правду написал — инлайнит и падает.
VC7 под рукой нету
R>Наконец понял R>Правда без собственных тестов не обошлось. Пришлось заменить __inline на __forceinline, т.к. иначе всё работало и под релизом... R>Мой вывод такой:
R>Вот описание функции из MSDN: R>
R>_alloca allocates size bytes from the program stack. The allocated space is automatically freed when the calling function exits (not when the allocation merely passes out of scope)
R>А фактически получается, что работает так: R>
R>_alloca allocates size bytes from the program stack. The allocated space is automatically freed when the first non-inlined calling function exits (not when the calling function exits and not when the allocation merely passes out of scope)
R>Основная проблема в том, что нельзя угадать как компилятор заинлайнит функции.
Имхо, это просто тупая бага компилятора, за которую нужно отрывать руки. Мне лично плевать, что там делает оптимизатор\линкер — инлайнит или нет. Я описал валидную языковую конструкцию, значит, она должна при любой агрессивной оптимизации работать — иначе это уже не оптимизация. Вариантов у компилятора как минимум 2 — либо правильно инлайнить (как делает, по моим воспоминаям, ватком — там это был обычный прием оптимизации — вынести alloca в отдельную функцию), при этом восстанавливая стек фрейм (больших проблем в кодогенерации я тут не вижу — да вообще никаких проблем не вижу, тем более сейчас компилятор пытается это делать, используя для адресации локальных переменных ebp (именно и только в такой функции) и сохраняя и восстанавливая значение esp (правда, немного не в том месте). Либо не инлайнить вообще, как поступает gcс (что чревато, поскольку это один из приемов оптимизации).
Здравствуйте, Andrew S, Вы писали:
AS>Имхо, это просто тупая бага компилятора, за которую нужно отрывать руки. Мне лично плевать, что там делает оптимизатор\линкер — инлайнит или нет. Я описал валидную языковую конструкцию, значит, она должна при любой агрессивной оптимизации работать — иначе это уже не оптимизация. Вариантов у компилятора как минимум 2 — либо правильно инлайнить (как делает, по моим воспоминаям, ватком — там это был обычный прием оптимизации — вынести alloca в отдельную функцию), при этом восстанавливая стек фрейм (больших проблем в кодогенерации я тут не вижу — да вообще никаких проблем не вижу, тем более сейчас компилятор пытается это делать, используя для адресации локальных переменных ebp (именно и только в такой функции) и сохраняя и восстанавливая значение esp (правда, немного не в том месте). Либо не инлайнить вообще, как поступает gcс (что чревато, поскольку это один из приемов оптимизации).
void allo() __attribute__((always_inline));
void allo()
{
alloca(1024 * 500); // 500k
}
int main()
{
for (int x = 0; x < 8; ++x)
allo();
}
gcc4.1.1 — stack overflow
компилирую с -O3 больше никаких опций нет
причём если сделать цикл до 4, то не падает
если он складывает все стеки, то 500k * 4 = 2М
а если не складывает, то почему при 8 падает
R>void allo() __attribute__((always_inline));
R>void allo()
R>{
R> alloca(1024 * 500); // 500k
R>}
R>int main()
R>{
R> for (int x = 0; x < 8; ++x)
R> allo();
R>}
R>
R>gcc4.1.1 — stack overflow
R>компилирую с -O3 больше никаких опций нет R>причём если сделать цикл до 4, то не падает R>если он складывает все стеки, то 500k * 4 = 2М R>а если не складывает, то почему при 8 падает
Может, в данном случае он просто разворачивает цикл? Конечно, это не оправдывает некорректной работы результата.
говорят, что ничего не падает... очная ставка! R>Там говорят отчасти правду, позор на мои седины. R>На 2005.sp1 оно работает правильно, это у меня ошибка в коде R>Там компилер присутствие alloca воспринимает весьма однозначно. R>1. функция не будет заинлайнена R>2. функция не будет заинлайнена даже если вызов alloca будет выброшен в процессе оптимизации R>3. в функции будет сгенерирован пролог и эпилог проверяющий состояние стека.
R>про VC6 правду написал — инлайнит и падает. R>VC7 под рукой нету
под vc71 всё плохо
а ты попробуй на 2005.sp1 включить максимальные оптимизации, у меня тоже не сразу получилось под vc71
В частности:
Optimization — O2
Inline Function Expansion — Any Suitable
void traceIt( void* a )
{
std::cout << "Trace address:" << (int)a << std::endl;
}
void allo() __attribute__((always_inline));
void allo()
{
void * p = alloca(1024 * 500); // 500k
traceIt( p );
}
int main()
{
for (int x = 0; x < 8; ++x)
allo();
}
Чито так пишет?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Andrew S, Вы писали:
R>>gcc4.1.1 — stack overflow
R>>компилирую с -O3 больше никаких опций нет R>>причём если сделать цикл до 4, то не падает R>>если он складывает все стеки, то 500k * 4 = 2М R>>а если не складывает, то почему при 8 падает
AS>Может, в данном случае он просто разворачивает цикл? Конечно, это не оправдывает некорректной работы результата.
Я чо-то не понимаю по асму — там белибирда какая-то...
Но видимо что-то типа того. Тем не менее суть остаётся прежней — у gcc тоже с этим плохо
Ну вот его и заловили с поличным
R>
Взаимно: , хоть мне и нельзя
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, remark, Вы писали:
R>До смерти выдал:
R>
R>Trace address:245504
А если цикл до 4 крутить, то типа пролащит ещё?
Типа повезло с константами?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
говорят, что ничего не падает... очная ставка! R>>Там говорят отчасти правду, позор на мои седины. R>>На 2005.sp1 оно работает правильно, это у меня ошибка в коде R>>Там компилер присутствие alloca воспринимает весьма однозначно. R>>1. функция не будет заинлайнена R>>2. функция не будет заинлайнена даже если вызов alloca будет выброшен в процессе оптимизации R>>3. в функции будет сгенерирован пролог и эпилог проверяющий состояние стека.
R>>про VC6 правду написал — инлайнит и падает. R>>VC7 под рукой нету
R>под vc71 всё плохо
R>а ты попробуй на 2005.sp1 включить максимальные оптимизации, у меня тоже не сразу получилось под vc71 R>В частности: R>Optimization — O2 R>Inline Function Expansion — Any Suitable
Пробовал, не надает.
R>Так же попробуй __forceinline
пробовал -не падает