LINUX.ORG.RU

Проясните про malloc

 


0

6

Если код будет 100% выполнятся только на linux/freebsd (ну, чисто теоретически, mac, если у меня он когда-нибудь будет чтобы протестировать), то нужно ли проверять возвращаемое значение *alloc функций? Я так понимаю, что на линуксах проверку похерили и оно всегда вернет значение, а потом во время выполнения чего-то важного просто упадет к чертям.

Есть какой-нибудь документ который явно говорит для этих трех систем что, мол, так и так, можете не проверять, все равно бесполезно? И вообще, коль память кончилась - ты уже ничего не сделаешь, ни данные не сохранишь, ни сеанс - падай как можно быстрее, чтобы другие выжили.

P.S. Куда дели теги «си» и «pure c»?


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

1. man malloc в линуксах сделай, ошибки возвращаться могут, с чего бы нет-то?

Слышал очень много разговоров о том, что это надо специально с overcommit флагами играться, чтобы NULL получить.

Moreo
() автор топика

Как это не нужно? Обязательно нужно. С чего ты взял, что в системе хватит памяти для твоих хотелок?

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

Знаю такие разговоры.

Но я бы посоветовал писать код так, как учат в книжках. Дефолтное поведение ядра Линукс может 100 раз поменяться, и что, весь код всех продуктов на свете перелопачивать? От себя рекомендую сверяться с CERT C Secure Coding Standards. Там умные дядьки всё взвесили и выписали. Если есть вопрос - спрашивать можно прямо там, есть комментирование статей.

Krieger_Od ★★
()
Последнее исправление: Krieger_Od (всего исправлений: 1)
Ответ на: комментарий от Moreo

Если памяти не хватит, то вернётся ошибка, ты её корректно в условиях программы обработаешь и завершишь работу либо ещё чего сделаешь.

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

Например написать, что не хватает памяти и завершить работу.

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

А что насчет надо падать сразу или нет в случае нехватки памяти?

Как в учебниках рекомендуют, так и делай.

Например написать, что не хватает памяти и завершить работу.

Krieger_Od ★★
()

Есть какой-нибудь документ который явно говорит для этих трех систем что, мол, так и так, можете не проверять, все равно бесполезно?

Проще найти документ, который утверждает обратное, и обычно это man 3 malloc в целевой системе.

NULL же получить элементарно: достаточно упереться в resource limit'ы системы, в OpenBSD, например, на amd64 по дефолту процессам разрешается использовать не больше 512M памяти.

На каком-нибудь шелл-хостинге можно встретить такое:

$ ulimit -a      
time(cpu-seconds)    unlimited
file(blocks)         unlimited
coredump(blocks)     unlimited
data(kbytes)         40960
stack(kbytes)        4096
lockedmem(kbytes)    2049204
memory(kbytes)       2049204
nofiles(descriptors) 50
processes            25

А то, что в Linux эти самые лимиты большинство не настраивает — это уже другой вопрос.

И вообще, коль память кончилась - ты уже ничего не сделаешь, ни данные не сохранишь, ни сеанс - падай как можно быстрее, чтобы другие выжили.

Не обязательно падать. Для какого-нибудь сетевого демона может быть огромным приемуществом вместо падения просто прекратить принимать новые соединения, но при этом продолжать обслуживать уже установленные.

И вообще, обычно просто пишут подобные обертки над malloc'ом:

http://bxr.su/OpenBSD/usr.bin/ssh/xmalloc.c#26
https://gitweb.torproject.org/tor.git/tree/src/common/util.c#n155

Чтобы потом можно было делать так: http://bxr.su/OpenBSD/usr.bin/ssh/auth2.c#119

edigaryev ★★★★★
()
Ответ на: комментарий от edigaryev
25void *
26xmalloc(size_t size)
27{
28    void *ptr;
29
30    if (size == 0)
31        fatal("xmalloc: zero size");
32    ptr = malloc(size);
33    if (ptr == NULL)
34        fatal("xmalloc: out of memory (allocating %zu bytes)", size);
35    return ptr;
36}

Интересно, как fatal печатает форматированную строку в условиях, когда malloc может не работать.

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

Статический буфер, скорее всего. Если не влезает, строка обрезается.

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

Главное чтобы оно не вызывало xmalloc у себя внутри :)

Иначе получится как с попыткой хукнуть malloc через LD_PRELOAD в Linux: для получения оригинального маллока нужно вызвать dlopen (хотя и не обязательно), который где-то по пути вызывает malloc, который мы успешно хукнули.

Чтобы работало приходится писать мини-аллокатор, использующий массивы символов на стеке, или юзать GNU-расширения. В той же OpenBSD, например, malloc в dlopen не используется, правда не уверен, что причина та же.

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

Писать жалобу тем, кто такие стандарты принял.

Но я с противоречащими стандартами как-то не сталкивался.

А ты, похоже, жирнишь.

cvs-255 ★★★★★
()
Последнее исправление: cvs-255 (всего исправлений: 1)
Ответ на: комментарий от anonymous

Невозможно писать одновременно на обоих языках, ты либо пишешь на C и следуешь его стандарту, либо то же самое с C++. Да и отличия там не такие уж большие

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

А чем тогда можно в сях вывести строку чтобы гарантированно не вызвать маллок по дороге? Подход мне нравится. А если просто exit(ERR_MALLOC_FAILED) ?

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

А чем тогда можно в сях вывести строку чтобы гарантированно не вызвать маллок по дороге?

write. Только это не C, а POSIX.

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

Где-то есть гарантия что write не аллоцирует память?

По факту скорее всего да, но и обычным printf/puts это тоже ни к чему.

anonymous
()

Я так понимаю, что на линуксах проверку похерили

Нет, если ты настроишь всякие оверкоммиты, будет ОК. Но в общем случае — да, не сработает. Поэтому я в большинстве случаев malloc заменяю на calloc.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Moreo

А чем тогда можно в сях вывести строку чтобы гарантированно не вызвать маллок по дороге?

Для POSIX — write(2).

Подход мне нравится. А если просто exit(ERR_MALLOC_FAILED) ?

Можно и так. Лишь бы юзер понял, что случилось.

Legioner ★★★★★
()
/*
* Memory allocation
*/
#define ALLOC(type, var, size) type * var = ((type *)my_alloc(size, sizeof(type)))
#define MALLOC(type, size) ((type *)my_alloc(size, sizeof(type)))
#define FREE(ptr) do{free(ptr); ptr = NULL;}while(0)

my_alloc

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от anonymous

Где-то есть гарантия что write не аллоцирует память?

Системный вызов можно сделать и напрямую, в обход либц.

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

Я один раз вообще бустом воспользовался, хоть на сях собирал... Но в принципе, предпочитаю делать без всякого внешнего говна. А макросы — это хорошо. Очень сильно упрощают чтение кода. Разве что объем увеличивают — из-за этого нужно очень осторожно пользоваться макросами при написании прошивок для мелкоконтроллеров.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Bfgeshka

Например можно для оптимизации кешировать некоторые данные. При нехватке памяти можно почистить низкоприоритетные кеши и высвободить память.

mamba_namba_karamba
()

При попытке навыделять больше, чем всё адресное пространство, malloc выплюнет ноль. У 32-битных процессов этот лимит весьма скромненький, порой даже меньше, чем реально доступная системе оперативка. Ну и отключение overcommit или установка лимитов - вполне штатные фичи, которые могут свалиться на голову твоей программе.

Не проверять можно в том случае, если ты решишь, что тебе влом продумывать стратегию восстановления после таких ошибок или даже сохранения консистентности данных. Ну то есть если закрыть глаза, то проблемы как бы и нет.

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

Я один раз вообще бустом воспользовался, хоть на сях собирал...

Вместо тысячи слов... и тысячи тредов с тегом «рукожопие»

Deleted
()

Обертывай в какой-нибудь my_malloc и делай abort если вернулся NULL. Заказчику скажешь «хотите нормальной обработке — удваивайте сроки»

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

Просто обработка одного макроса бустом оказалась веселее, нежели запись этого макроса только средствами cpp. Это мне на SO подсказали. Правда, несмотря на все, хоть запись и была короче, да и собиралось оно всего на пару секунд дольше, я таки оставил свой лисапедный жирнючий вариант — тупо потому, что я его понимал (в отличие от предложенного на бусте).

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от yurikoles

Медперсонал уже потёр. Причём, из моих избранных тегов тоже.
Раньше был ещё тег "сишечка", а теперь жри, что дают.

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

Ну и отключение overcommit

Ты наверное хотел сказать «включение»?

или установка лимитов

И то и другое - проблема того, кто крутит.

Не проверять можно в том случае, если ты решишь, что тебе влом продумывать стратегию восстановления после таких ошибок

Уважаемый эксперт, если вы нихрена не понимаете в теме, то зачем вы кукарекаете? Я задам лишь один вопрос, который ТС уже поднял, но наверное экперт его не понял.

Что гарантирует доступность памяти после успешного возврата маллока? Конкретно.

восстановления после таких ошибок

И на каких же «механизмах» основывается это «восстановления после таких ошибок» от иксперта? Где они реализованы?

даже сохранения консистентности данных

Я тебя удивлю, но маллок ничего не гарантирует, а следовательно все модели основанные на нём являются фиктивными.

Ну то есть если закрыть глаза, то проблемы как бы и нет.

Так смешно это от нуля читать, хотя ведь проверка маллока это и есть «закрыть глаза».

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

А какое отношение к системе и памяти имеет маллок? Ответь на вопрос, перед икспертными заявлениями.

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

Эти иксперты.

Как это наверное трудно, когда в голове пустота.

Давай поясню, понимаешь, вася. Для того, чтобы кукарекать об «не падает» - тебе надо доказать, что «удачный возврат маллока» гарантирует «не упадаёт».

Пока что, никто этого не доказал. Но что самое смешное - об этом даже в мануале написано, но ведь иксперты о них только кукарекают.

Далее, кукарекая об «системаХ» и об «маллоке», т.е. либц - надо гарантировать возможность работы либц без памяти, но этого то же ничего не гарантирует. Вернее все кругом гарантируют обратное.

И вообще, обычно просто пишут подобные обертки над malloc'ом:

Буду никомпетентным мусором можно и не такое написать:

fatal(«xmalloc: out of memory (allocating %zu bytes)», size);

Сегфолт.

n = atomicio(read, fd, banner, len);

Сегфолт.

А так да - впиндюрить бесполезное дермище и кукарекать «не упадёт» - типичное поведение икспертов.

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

Специально для знатаков.

Сегфолт.

Ну как бэ естественно там будут не сегфолты, а в первом случае упадёт/зависнет, а во втором просто kill.

Чтоб тут лалки не пытались меня в чем-то уличать.

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

А какое отношение к системе и памяти имеет маллок?

malloc использует системные вызовы для выделения памяти и при нехватке памяти в системе вернёт NULL.

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