The OpenNET Project / Index page

[ новости /+++ | форум | теги | ]



"Выпуск GNU Wget 1.21"
Версия для распечатки Пред. тема | След. тема
Форум Разговоры, обсуждение новостей
Исходное сообщение [ Отслеживать ]
Заметили полезную информацию ? Пожалуйста добавьте в FAQ на WIKI.
. "Выпуск GNU Wget 1.21" +1 +/
Сообщение от Ordu (ok), 01-Янв-21, 21:18 
> Я так понимаю, это библиотечная функция для выделения памяти.

Да, библиотечная. Но она выделяет на стеке. А стек -- хрупкая штука. Во многих проектах alloca вообще под запретом, и за её использование руки отрывают.

>        void *alloca(size_t size);
> DESCRIPTION
>       The  alloca()  function  allocates  size  bytes of space in the stack
>       frame of the caller.  This temporary  space  is  automatically  freed
>       when the function that called alloca() returns to its caller.
> RETURN VALUE
>       The alloca() function returns a pointer to the beginning of the allo‐
>       cated space.  If the allocation causes stack overflow, program behav‐
>       ior is undefined.

Чуешь? Тут документированный UB, и (что очень в стиле unix-way) этот UB невозможно гарантированно обойти. Вызывая alloca, ты никогда не знаешь, будет ли переполнение стека или нет. И узнать не можешь. Но alloca -- это очень быстрый способ выделить/освободить память, гораздо быстрее чем malloc. Поэтому возникает соблазн забить на потенциальные проблемы, и использовать alloca вместо malloc. И есть те, кто перед таким соблазном устоять не может.

Если выделять немного, то в принципе ничего плохого не должно случиться. Но что значит "немного"? И это ж надо проверить, так уж ли немного мы собираемся выделить? А если мы проверили, и оказалось много, то что делать?

То есть, "немного" ведь означает не больше N, где N -- известное на этапе компиляции целое число. А если мы можем написать:

char *buf = NULL;
if(size <= 256) {
    buf = alloca(size);
} else {
    die("Invalid size"); // в смысле die -- это no-return функция
}

то мы с тем же успехом можем написать и:

if(size > 256) {
    die("Invalid size");
}
char buf[256];

Тут выходит, что выделяется 256-size лишних байт, но... и чё с того? Это может иметь значение при рекурсивном вызове, но использовать alloca в рекурсивной функции может только полнейший отморозок.

То есть alloca оказывается не нужен в такой ситуации. А если size может исчисляться мегабайтами, и мы считаем что наша программа должна работать с такими size, то придётся пользовать malloc, потому как условно использовать alloca или malloc в зависимости от размера -- это то же самое, что открывать нараспашку все двери, вешая над ними транспаранты "MEMORY BUGS ARE WELCOME!". Причём, в такой ситуации, скорее всего и выигрыша по скорости не будет никакого существенного: если программа норм работает с мегабайтовыми буферами, выделенными при помощи malloc, она тем более будет норм работать с докилобайтовыми буферами, выделенными при помощи malloc.

Может можно придумать какой-нибудь use-case для alloca, когда это не будет хождениями по граблям переполнения стека AND даст прирост в скорости, но, во-первых, мне не удаётся придумать, во-вторых, это будет очень специальным случаем, и это будет раскладыванием граблей для будущих разработчиков.

Ответить | Правка | Наверх | Cообщить модератору

Оглавление
Выпуск GNU Wget 1.21, opennews, 01-Янв-21, 10:46  [смотреть все]
Форумы | Темы | Пред. тема | След. тема



Партнёры:
PostgresPro
Inferno Solutions
Hosting by Hoster.ru
Хостинг:

Закладки на сайте
Проследить за страницей
Created 1996-2024 by Maxim Chirkov
Добавить, Поддержать, Вебмастеру