Заставить malloc () возвращать NULL вместо сбоя программы? - PullRequest
4 голосов
/ 19 августа 2010

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

Как я могу это исправить?

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

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

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

Ответы [ 5 ]

2 голосов
/ 19 августа 2010

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

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

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

1 голос
/ 19 августа 2010

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

1 голос
/ 19 августа 2010

Странно ... следующее работает для меня, если я скомпилирую его из командной строки.Время выполнения malloc имеет много опций, как упомянул Спенсер .Если вы используете 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;
}

Кстати: это в debug или release построить?Возможно, XCode пытается вам как-то помочь.

1 голос
/ 19 августа 2010

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

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

0 голосов
/ 03 сентября 2013

Как уже говорили другие, очень вероятно, что вы перезаписали некоторое внутреннее состояние 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
...