Заставить malloc () возвращать NULL вместо сбоя программы?



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



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



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



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




Программа получила сигнал: "EXC_BAD_ACCESS".

sharedlibrary применять нагрузки-правила все

предупреждение: невозможно восстановить ранее выбранный кадр.

Формататоры данных временно недоступны, повторите попытку после "продолжить". (Отлаживаемая программа сигнализировала, находясь в функции, вызываемой из GDB.

GDB остается в кадре, где был получен сигнал.

Чтобы изменить это поведение, используйте "set unwindonsignal on"

Вычисление выражения, содержащего функцию (dlopen), будет отменено.)

Нет памяти, доступной для программирования сейчас: небезопасно вызывать malloc


749   5  

5 ответов:

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

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

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

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

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

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

Странно ... следующее работает для меня, если я компилирую его из командной строки. Среда выполнения, поставляемая 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 build? Возможно, XCode пытается как-то помочь вам.

Как уже говорили другие, очень вероятно, что вы перезаписали какое-то внутреннее состояние 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 на crack. Вы можете прочитать об этом здесь: https://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/libgmalloc.3.html

Вы бы запустили свою программу так:

DYLD_INSERT_LIBRARIES=/usr/lib/libgmalloc.dylib ./myProg

Comments

    Ничего не найдено.