LINUX.ORG.RU

Почему надо проверять malloc на NULL

 , ,


0

2

Вообще выделение памяти проверять.

А вот потому что:

#include <stdio.h>
int main()
{
  unsigned char *a = NULL;
  int b = 0;
  unsigned long n = (unsigned long)&b;
 
  printf("b = %d, n = %lu\n",b,n);
  a[n]=1;
  printf("b = %d\n",b);
  return 0;
}

Запуск

$ gcc nullptr.c -o nullptr
$ ./nullptr 
b = 0, n = 140731726099148
b = 1

Запускалось в 64-битном (x86_64) Linux. Как видно, никаких сегфолтов и прочих ошибок. Конечно, адрес в районе 127 Тб в примере далеко за пределами доступного почти на всех компьютерах, но нет никаких гарантий, что на какой-то системе с каким-то компилятором и настройками среды значение не окажется более доступным. Могут быть и другие архитектуры (32-битные например), если запускать от root'а, то в начало может быть разрешена запись и там иметься память процесса. Или ещё какие-то варианты.

shdown, monk, liksys, Xenius - я думаю вам понравится. Пример сочинился по ходу чтения обсуждения Вышло издание 2,92 книги «Программирование: введение в профессию» А. В. Столярова (комментарий)

★★★★★

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

Ну они не прямо так сделали:

Перехватываем libc’шный malloc()

Просто обернули вызов glibc-шного аллокатора в свою функцию.

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

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

при определённой изобретательности

Вопрос в том, какова вероятность, что процесс будет прибит OOM killer’ом vs malloc вернёт NULL, если память закончится.

В продакшене никогда не ловили, но вот на десктопе у меня если что-то кривое всю память отжирает, chromium постоянно сообщает, что процесс вкладки прибит 9-ым сигналом (SIGKILL; это значит, что пришёл OOM killer — всякое по типу systemd-oomd у меня выключено).

shdown ★★
()
Последнее исправление: shdown (всего исправлений: 1)

Проверять конечно нужно, но твой пример полностью не в тему. После malloc-а почти нигде не лезут сразу в его дальний конец, обычно инициализируют начиная с начала.

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

Потому что у тебя многозадачная ОС, это как минимум.

Многозадачные ОС были с 1969. А выдача больше памяти, чем есть, появилась где-то с Windows NT. Причём там это было сделано по уму: нехватка памяти не убивала процесс, а увеличивала своп. А Linux выдает всем сколько запросят, а потом прибивает кого-нибудь.

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

Видимо, придётся разжовывать прям до алфавита.

Запрос количества свободной памяти не имеет смысла, потому что здесь by design содержится race condition. Какое число бы тебе ни вернули, на результат полагаться нельзя.

При чём тут Windows NT, оверкоммит и прочая шизофазия, не ясно, потому что вопрос ветки был:

В стандартной библиотеке не предусмотрена кросплатформенная функция, чтобы узнать количество доступной памяти

И правильно, что не предусмотрена.

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

Запрос количества свободной памяти не имеет смысла, потому что здесь by design содержится race condition. Какое число бы тебе ни вернули, на результат полагаться нельзя.

Если бы malloc работал правильно, он был бы и не нужен.

И правильно, что не предусмотрена.

В Linux есть /proc/meminfo.

monk ★★★★★
()

Тема номера: если дверью прищемить яйца, то яйца окажутся прищемлены.

legolegs ★★★★★
()

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

a = malloc(...);
if(!a) abort();
Werenter ★★★
()

Как видно, никаких сегфолтов и прочих ошибок.

Потому что в программе нет ошибок.

Конечно, адрес в районе 127 Тб в примере далеко за пределами доступного почти на всех компьютерах,

Где вы увидели адрес в районе 127 тб? Нет там такого. Похоже что автор не понимает строку a[n]=1

Разберём: здесь a равно 0, n равен адресу b. Это эквивалентно [&b]=1, то есть в b записали 1. Никакой ошибки.

anonymous
()
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария