2015-08-11 4 views
3

В моей программе C Я пытаюсь выделить память с функцией таНос(), например:Как обнаружить, что функция malloc() не будет выполнена?

char *buf = (char *)malloc(size); 

, но проблема в том, что таНос() всегда возвращает ненулевой указатель. Даже если я попытаюсь выделить огромный (размер - 1E + 13) объем памяти, он возвращает действительный buf Указатель. Конечно, после этого программа выйдет из строя.

Но как я могу определить, что запрошенный объем памяти слишком велик и будет недоступен, если возвращается buf Значение не NULL?

Edit:

В комментариях я вижу, что мой вопрос может быть не ясно. Таким образом, это более развернутый пример:

unsigned long size = very_large_calculated_value; 
char *buf = (char *)malloc(size); 
if (buf == NULL) i_know_it_fails; 
... 

но Xcode работает этот код и Buf никогда не NULL независимо просили размера есть. Итак, очень скоро программа аварий. Как я могу обнаружить отказ в распределении памяти, если buf не является NULL, но, очевидно, не подлежит использованию?

Edit:

Для тех, кто отмечен вопрос как дубликат: Там нет ответа на вопрос: «Как я могу обнаружить ошибки распределения памяти?», Потому что решение, как «изменить некоторые параметры в ваша ОС "не является ответом - я прошу C-код обнаруживать ошибку выделения памяти или что-то вроде« невозможно сделать программно ».

+0

http://en.cppreference.com/w/c/memory/malloc – juanchopanza

+3

Что вы имеете в виду, когда говорите «он возвращает действительный указатель buf. Конечно, после того, как программа сработает». У вас есть код, демонстрирующий такое поведение? – dbush

+2

Стандартное предупреждение: не бросать 'void *', как было возвращено 'malloc' & friends. C ** не ** C++! – Olaf

ответ

2

malloc() всегда возвращает непустой указатель

Это не совсем верно.

В случае отказа malloc() он вернет NULL. Вам необходимо проверить возвращаемое значение malloc() (указатель) против NULL, чтобы гарантировать, что malloc() является успешным.

Процитирую страницу человека, (курсив мой)

В malloc() и calloc() возвращают указатель на выделенную память, которая надлежащим образом выровнены для любого вида переменной. При ошибке эти функции возвращают NULL. [...]


Примечание; [После комментариев]

Если вы говорите о оптимистичных методах распределения, используемых malloc() вернуть указатель, в этом случае нет стандарта способа проверки или предсказать будущего провал, в случае, если malloc() вернул указатель не-NULL. Если вы хотите быть уверенным в доступности памяти, вы можете вместо этого использовать calloc().

+5

Он ищет способ предсказать сбой, потому что на некоторых системах 'malloc()' будет успешным, хватит ли свободной памяти или нет (такие системы могут не захватывать память до тех пор, пока вы не получите доступ к ней, получится ошибка, если этого недостаточно). – Dmitri

+0

Точка, что на некоторых системах 'malloc' может вернуть что-то виртуальное, а затем выйти из строя. Позвольте мне выкопать для соответствующей дискуссии ... –

+0

@Dmitri Я не думаю, что это тот случай _here_, пожалуйста, обратите внимание на утверждение: «malloc() всегда возвращает указатель не-NULL« –

3

Невозможно до предсказать отказ памяти. Единственный способ - проверить возвращаемое значение malloc() для нулевого указателя.

Кажется, что ваш вопрос действительно о памяти overcommit сделан ядром. Использование которого ядро ​​никогда не возвращает нулевой указатель. Значение по умолчанию - всегда overcommit. Таким образом, чтобы отключить его на Linux-подобных систем делают:

echo 2 > /proc/sys/vm/overcommit_memory 

Или вы могли бы сделать то же самое с помощью sysctl:

sysctl vm.overcommit_memory=2 

Оба эквивалентны.

Значение 2 должно гарантировать, что malloc возвращает нулевой указатель в случае, если запрашиваемая память превышает доступную физическую память (плюс пространство подкачки).

+0

Если вы используете ядро, которое заботится о/proc и принимает эти параметры и т. Д., Конечно, не связано рамкой тегов (C, XCode) ... –

+0

@GradyPlayer Даже не-подобный- proc-BSD разрешают определенные изменения через sysctl. Метки должны быть ориентиром для релевантности. Если выясняется, что правильные теги правильны или нет, я не вижу никаких проблем при ответе на него. Если ОП разъяснит, что это не случай, тогда я счастлив удалить свой ответ. –

+0

Ваша точка зрения о перекомпоновке полностью верна, и она ставит вопрос ... Я просто указываю, что ваше средство очень специфично для одного типа системы. –

2

Развивая ответ BlueMoon, вот это то, что man page for malloc должен сказать о overcomitting:

ОШИБКИ

По умолчанию Linux следует за выделение стратегии оптимистичной памяти. Это означает, что когда malloc() возвращает не-NULL, не гарантирует, что память действительно доступна. Это очень плохая ошибка. В случае, если окажется, что система находится вне памяти , один или несколько процессов будут убиты печально известным OOM убийцей. В случае Linux используется в условиях, когда он бы менее желательным, чтобы внезапно потерять некоторые случайно выбрал процессы, а кроме того, ядро ​​версии появились достаточно недавно, можно отключить эту overcommitting поведение с помощью команды как # echo 2 > /proc/sys/vm/overcommit_memory
См. Также каталог документации, файлы vm/overcommit-accounting и sysctl/vm.txt.

+1

OP добавил тег «XCode», поэтому я предполагаю это для OS-X, а не для Linux. (Хотя я подозреваю, что поведение похоже) – Olaf

1

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

В общем, если удалять все контрольные точки, тогда код запускается как следует, без каких-либо проблем. Но если некоторые точки останова вставлены (влияние их положения в коде для меня неясно), то Xcode становится неустойчивым и падает после функций выделения памяти.

+0

«Я нашел программное решение для этой проблемы» - это совсем не похоже на захватывающее программное решение, для которого этот вопрос был вновь открыт. Неудовлетворительно .... –

Смежные вопросы