Re: Бойтесь alloca
От: superlexx  
Дата: 27.03.07 18:26
Оценка:
Здравствуйте, rm822, Вы писали:
R>- неуловимый баг

в восьмёрке code analysis ругается:
warning C6263: Using _alloca in a loop: this can quickly overflow stack
Re[3]: Бойтесь alloca
От: remark Россия http://www.1024cores.net/
Дата: 27.03.07 19:24
Оценка:
Здравствуйте, rm822, Вы писали:

R>>Вот это, конечно, неприятно, если это действительно так...

R>Reproduced!
R>здесь

R>характерно что на VC6 чтобы упасть ему нужен Inline

R>а на VS2005 этот инлайн можно смело убрать и он все равно падает.

А вот здесь
Автор: Programador
Дата: 27.03.07
говорят, что ничего не падает... очная ставка!


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[3]: Бойтесь alloca
От: remark Россия http://www.1024cores.net/
Дата: 27.03.07 19:25
Оценка:
Здравствуйте, Кодт, Вы писали:

R>>Вот это, конечно, неприятно, если это действительно так...


К>Здесь, формально, выход из функции есть, а реально его нет (оптимизатор выбросил ненужный, по его мнению, код пролога-эпилога).


В вот здесь
Автор: Programador
Дата: 27.03.07
говорят, что всё работает... где же правда?


1024cores — all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[4]: Бойтесь alloca
От: Andrew S Россия http://alchemy-lab.com
Дата: 27.03.07 22:54
Оценка: 18 (1)
R>>>Вот это, конечно, неприятно, если это действительно так...

К>>Здесь, формально, выход из функции есть, а реально его нет (оптимизатор выбросил ненужный, по его мнению, код пролога-эпилога).


R>В вот здесь
Автор: Programador
Дата: 27.03.07
говорят, что всё работает... где же правда?


Правда в том, что не работает.
Вот пример:


#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 и затем его восстанавливает), но безуспешно. Да, измерения можно расставлять по вкусу — как в теле цикла, так и вне — это сути не меняет.
http://www.rusyaz.ru/pr — стараемся писАть по-русски
Re[12]: Бойтесь alloca
От: red_dragon Украина  
Дата: 28.03.07 06:17
Оценка: :))
Здравствуйте, gear nuke, Вы писали:

GN>А при new возможен std::bad_alloc


ну это можно отключить
Re[14]: Бойтесь alloca
От: ДимДимыч Украина http://klug.org.ua
Дата: 28.03.07 07:35
Оценка:
Здравствуйте, remark, Вы писали:

R>Правильнее сказать — в линуксе тоже есть access violation, просто он чаще называется segmentation fault



Когда segmentation fault появился, виндовс еще в проекте не было. См. здесь, например.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[15]: Бойтесь alloca
От: remark Россия http://www.1024cores.net/
Дата: 28.03.07 08:34
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

ДД>Здравствуйте, 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'ом по ламерски


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[16]: Бойтесь alloca
От: ДимДимыч Украина http://klug.org.ua
Дата: 28.03.07 09:00
Оценка:
Здравствуйте, remark, Вы писали:

R>В смысле?


В смысле, что термин "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'ом по ламерски


Миллионы разработчиков с Вами не согласны
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[17]: Бойтесь alloca
От: remark Россия http://www.1024cores.net/
Дата: 28.03.07 09:42
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

ДД>Еще раз. Ситуация "segmentation fault" возникает, когда программа обращается к памяти неприемлимым для нее способом: пишет в защищенную от записи область, читает недоступный участок и т.д. Каким образом память защищена — на уровне сегментов, страниц или еще как — это не важно. А уже на разных архитектурах эта ситуация приводит к разным последствиям: в unix-like это посылка сигнала SIGSEGV, в windows — исключение STATUS_ACCESS_VIOLATION.


Вот видишь как длинно приходится объяснять значение термина из-за плохо выбранного названия. Приходится говорить, что ошибка сегментации на самом деле может быть вызвана ошибкой пейджинга...
В windows из-за хорошо подобранного названия всё получается просто: ACCESS_VIOLATION — ошибка зашиты памяти.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[5]: Бойтесь alloca
От: remark Россия http://www.1024cores.net/
Дата: 28.03.07 09:49
Оценка:
Здравствуйте, 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. Понятно, что это можно забыть или не иметь доступ к коду.
Либо можно использовать свои буферы на стеке или глобальные. Тут минус, что неэкономно будет расходоваться стековое пространство, т.к. буфер придётся делать "максимального" размера.

Вобщем печально, конечно...


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[18]: Бойтесь alloca
От: ДимДимыч Украина http://klug.org.ua
Дата: 28.03.07 10:03
Оценка:
Здравствуйте, remark, Вы писали:

R>В windows из-за хорошо подобранного названия всё получается просто: ACCESS_VIOLATION — ошибка зашиты памяти.


Если быть точным, то "нарушение доступа". Хорошо, что PERMISSION_DENIED не назвали

R>


Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Re[6]: Бойтесь alloca
От: remark Россия http://www.1024cores.net/
Дата: 28.03.07 10:04
Оценка:
Здравствуйте, remark, Вы писали:

R>Здравствуйте, Andrew S, Вы писали:


AS>>Правда в том, что не работает.

AS>>Достаточно попробовать в дебаге и в релизе. Хотя, судя по листингу, VC честно пытается восстановить стек-фрейм (сохраняет esp и затем его восстанавливает), но безуспешно. Да, измерения можно расставлять по вкусу — как в теле цикла, так и вне — это сути не меняет.

R>Наконец понял

R>Правда без собственных тестов не обошлось. Пришлось заменить __inline на __forceinline, т.к. иначе всё работало и под релизом...

Я проверял под msvc71. Но эти @#$%^ уже не дают регистрировать баги на msvc71 только на msvc2005/2005sp1/Orcas — вот @#$#%, поддержка 2003 что ли закончилась?
На msvc2005/2005sp1 такая же фигня или поправили?

R>


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[6]: Бойтесь alloca
От: red_dragon Украина  
Дата: 28.03.07 10:20
Оценка:
Здравствуйте, remark, Вы писали:

R>Основная проблема в том, что нельзя угадать как компилятор заинлайнит функции.


Поэтому не стоит использовать такие низкоуровневые средства управляния памятью, как alloc в inline-функциях
Re[7]: Бойтесь alloca
От: remark Россия http://www.1024cores.net/
Дата: 28.03.07 10:29
Оценка: +1
Здравствуйте, red_dragon, Вы писали:

_>Здравствуйте, remark, Вы писали:


R>>Основная проблема в том, что нельзя угадать как компилятор заинлайнит функции.


_>Поэтому не стоит использовать такие низкоуровневые средства управляния памятью, как alloc в inline-функциях


Ты путаешь понятия: inline-функция, которая объявлена как inline (явно или неявно) и inline-функция, которая реально заинлайнена компилятором при генерации кода.


1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[8]: Бойтесь alloca
От: red_dragon Украина  
Дата: 28.03.07 10:39
Оценка: :)
Здравствуйте, remark, Вы писали:

R>Ты путаешь понятия: inline-функция, которая объявлена как inline (явно или неявно) и inline-функция, которая реально заинлайнена компилятором при генерации кода.


Разве? А что компилятор может инлайнить ф-ции, которые никаким образом не объявлены инлайн? По-моему даже при самой максимальной оптимизации, компиляторы таким не занимаются. Или я ошибаюсь
Re[19]: Бойтесь alloca
От: Erop Россия  
Дата: 28.03.07 10:44
Оценка:
Здравствуйте, ДимДимыч, Вы писали:

R>>В windows из-за хорошо подобранного названия всё получается просто: ACCESS_VIOLATION — ошибка зашиты памяти.

ДД>Если быть точным, то "нарушение доступа". Хорошо, что PERMISSION_DENIED не назвали
Это ты про UNIX-like?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[9]: Бойтесь alloca
От: remark Россия http://www.1024cores.net/
Дата: 28.03.07 10:47
Оценка:
Здравствуйте, red_dragon, Вы писали:

_>Здравствуйте, remark, Вы писали:


R>>Ты путаешь понятия: inline-функция, которая объявлена как inline (явно или неявно) и inline-функция, которая реально заинлайнена компилятором при генерации кода.


_>Разве? А что компилятор может инлайнить ф-ции, которые никаким образом не объявлены инлайн? По-моему даже при самой максимальной оптимизации, компиляторы таким не занимаются. Или я ошибаюсь


Сейчас фактически на современных компиляторах эти два множества никак не связаны. Т.е. может инлайнится то, что не объялено инлайн, может не инлайнится то, что объявлено.
Более того, может инлайнится даже то, что вынесено в отдельную единицу трансляции.
Частично решают проблему такие вещи как __forceinline, __declspec(noinline). Но я точно знаю, что и __forceinline может быть не заинлайнен — при этом выдаётся варнинг. Но тут проблема — тебе уже надо не просто "не стоит использовать такие низкоуровневые средства управляния памятью, как alloc в inline-функциях", а найти все такие функции в своём коде, найти все такие функции в системных и сторонних библиотеках и пометить их как __declspec(noinline) и надеятся, что так и будет. И потом на протяжении всей жизни следить за изменениями в в системных и сторонних библиотеках на предмет появления новых функций.



1024cores &mdash; all about multithreading, multicore, concurrency, parallelism, lock-free algorithms
Re[9]: Бойтесь alloca
От: Erop Россия  
Дата: 28.03.07 10:49
Оценка:
Здравствуйте, red_dragon, Вы писали:

_>Разве? А что компилятор может инлайнить ф-ции, которые никаким образом не объявлены инлайн? По-моему даже при самой максимальной оптимизации, компиляторы таким не занимаются. Или я ошибаюсь


Ошибаешься.
Уже довольно давно компиляторы пытаются использовать информацию из определения функции, если оно доступно в точке вызова.
Так что слово inline уже давно довольно влияет только на ODR

А теперь компиляторы уже умеют использовать и определениея, которые в точке вызова не видны
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[6]: Есть и хорошие новости :)
От: Erop Россия  
Дата: 28.03.07 10:52
Оценка:
Здравствуйте, remark, Вы писали:

R>Частично заткнуть проблему можно добавляя __declspec(noinline) к функциям, использующим alloca. Понятно, что это можно забыть или не иметь доступ к коду.

R>Либо можно использовать свои буферы на стеке или глобальные. Тут минус, что неэкономно будет расходоваться стековое пространство, т.к. буфер придётся делать "максимального" размера.

Вовсе не всё так плохо! Вполне достаточно аллокировать на стеке место под "типичный большой" запрос
Автор: Erop
Дата: 27.02.07
. А это, как правило, не так уж обременительно
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Бойтесь alloca
От: red_dragon Украина  
Дата: 28.03.07 11:07
Оценка:
Здравствуйте, Erop, Вы писали:
E>А теперь компиляторы уже умеют использовать и определениея, которые в точке вызова не видны

Может кто-нибудь выложить ассемблерный код сгенерированный компилятором из следующего исходника:

#include <malloc.h>

/*inline*/ int z()
{
    char *c = (char*)alloca(10000);
    return 3;
}

int main()
{
    int x = z();
    return x;
}

При включенной максимальной оптимизации, и чтобы компилер при этом заинлайнил ф-цию z()

Мой (minGW) не инлайнит, даже если указать inline z()
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.