2010-08-19 2 views
4

Я выделяю память в программе на C, используя malloc. Моя программа может выделять больше памяти, чем у системы есть место, после чего программа выйдет из строя. Для моих целей было бы лучше, если бы malloc просто вернул NULL (вроде, видимо, supposed to), поэтому я могу поймать ошибку. Вместо этого он выдает сообщение об ошибке «Нет памяти для программирования сейчас: небезопасно вызывать malloc». И сбой программы.Сделать malloc() вернуть NULL вместо сбоя программы?

Как это исправить?

Редактировать: Я знаю, что программа рушится сама по себе, а не потому, что я пытаюсь ссылаться на нулевой указатель. Программа никогда напрямую не вызывает malloc, но вместо этого вызывает функцию, которую я написал, которая вызывает malloc, а затем проверяет, возвращает ли она NULL. Он никогда не говорит, что malloc вернулся NULL.

Edit 2: Если это полезно, здесь полный вывод ошибок:

Программа получила сигнал: «EXC_BAD_ACCESS».
sharedlibrary apply-load-rules all
предупреждение: невозможно восстановить ранее выбранный кадр.
Data Formatters временно недоступны, повторите попытку после продолжения. (Отлаживаемая программа была сигнализируется в то время как функция вызывается из GDB.
GDB остается в кадре, где был получен сигнал.
Чтобы изменить это использование поведения «установить unwindonsignal на»
оценки экспрессии, содержащей функцию (dlopen) будет заброшены)
Нет памяти для программы в настоящее время:. небезопасная для вызова таНоса

+5

В зависимости от вашей операционной системы. Вы на Linux, Mac, Windows? – Potatoswatter

+1

Mac OS X Snow Leopard. (Я не уверен, что версия ОС имеет значение, но это не может повредить, чтобы знать.) –

+0

Не могли бы вы разместить функцию, которую вы вызываете malloc? – GWW

ответ

2

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

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

Все ответы танцуют вокруг того факта, что ошибки указателя являются единственным наиболее распространенным источником дефектов в коде С. Вам повезло, что вы получаете SIGBUS, который является свидетельством дефекта, который может быть широко отделен от того, где и когда происходит ошибка. Используйте valgrind, чтобы узнать, где находится настоящий дефект.

+0

+1 для valgrind.Если 'malloc()' делает невозможные вещи, тогда кажется вероятным, что вы случайно повредили часть кучи. – RBerteig

+0

Спасибо. Я установлю Valgrind. Вы заставляете меня думать, что, вероятно, что происходит, я помещаю слишком много материала в массив, и это заканчивается. –

+0

Упс, похоже, что Valgrind не поддерживается на OS 10.6. За исключением установки другой операционной системы, знаете ли вы о каких-либо похожих программах, которые работают на 10,6? –

1

Он проверяет, чтобы увидеть, если Malloc возвращает NULL? У вас может быть проблема с тестом равенства. Попробуйте что-то вроде «if (malloc (...)) then ...; еще ...; а не конкретной проверки.

Если это не поможет, тогда запустите только препроцессор и выясните, какой NULL «редактируется».

+0

"if (malloc (...)) then ...; else ..." имеет ту же проблему. NULL редактируется до (void *) 0, что вы ожидаете, не так ли? –

+0

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

1

Согласно this apple page, программа прерывается на основании ошибки malloc, если переменная окружения MallocErrorAbort включена в xcode. Чтобы отключить эту переменную, щелкните правой кнопкой мыши исполняемый файл в представлении «Дерево», выберите «Получить информацию» и перейдите на вкладку «Аргументы».

+0

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

+0

Затем я установил MallocErrorAbort в YES, и компилятор дал мне сообщение о том, что он включен. Программа разбилась так же. –

1

Странно ... для меня это сработает, если я скомпилирую его из командной строки. Время выполнения, заданное malloc, имеет a lot of options as Spencer mentioned. Если вы используете XCode, я бы поискал опцию, которая контролирует это.

#include <limits.h> 
#include <stdio.h> 
#include <stdlib.h> 


int 
main() 
{ 
    signed long long alloc_sz = (1 * 1024 * 1024 * 1024); 
    while (alloc_sz > 0ull) { 
     char *ptr = malloc(alloc_sz); 
     if (ptr == NULL) { 
      fprintf(stderr, "failed to allocate %llu bytes\n", 
        (unsigned long long)alloc_sz); 
      break; 
     } else { 
      free(ptr); 
      fprintf(stderr, "allocated %llu bytes\n", 
        (unsigned long long)alloc_sz); 
     } 
     alloc_sz *= 2ull; 
    } 
    return 0; 
} 

КСТАТИ: это в отладки или выпуска сборки? Возможно, XCode пытается каким-то образом помочь вам.

+0

Я запустил этот код, и он дал некоторый результат, а затем 'malloc' вернул NULL. Теперь мы знаем, что что-то другое вызывает проблему. BTW: сборка отладки. –

0

Как говорили другие, очень вероятно, что вы перезаписали какое-то внутреннее состояние malloc's, в результате чего он сделал странные вещи.

В Linux, как вы могли бы отслеживать это, было бы использовать valgrind. Если ваш код достаточно кросс-платформенный, вы можете запустить его в Linux (возможно, на виртуальной машине), я бы рекомендовал это сделать.

Если эта опция недоступна для вас, Mac OS X имеет свои собственные встроенные средства отладки. На высоком уровне есть инструменты. На более низком уровне malloc включит отладку в ответ на определенные переменные среды: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/malloc.3.html Прокрутите вниз до раздела ENVIRONMENT. Так, например, вы бы запустить программу с

MallocGuardEdges=1 ./myProg 

Вы также можете использовать libgmalloc, который, как malloc средства отладки на трещине. Вы можете прочитать об этом здесь: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/libgmalloc.3.html

Вы бы запустить программу, как это:

DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib ./myProg 
Смежные вопросы