Использование функций динамической памяти C в C ++, чтобы избежать ошибки сегментации - PullRequest
0 голосов
/ 28 сентября 2011

Я пытаюсь безопасно восстановиться после ошибки сегментации, которую я ожидаю. Я пытаюсь избежать проверки, используя мою функцию canAlloc () здесь. Когда canAllow возвращает значение false, A0 (который принадлежит Аккерманну, если вы его не видели) должен выдать исключение, которое я могу отловить в методе main. checkTable и saveInTable - это две функции, которые используют map<int hash, int value> для хранения возвратов из A0.

    bool canAlloc(){
     bool reBool = false;
     int * memch = (int*)calloc (10000, sizeof(int));
     reBool = (memch != NULL);
     free(memch);
     return reBool;
    }


    int A0(int m, int n){
if(!canAlloc()) throw;

int reInt = checkReturnTable(m,n);
if(reInt == -1){        
    if(m == 0){
        return n + 1;
    } else if(m > 0){
           if(n == 0){
                reInt = A0(m-1,1);
           } else if(n > 0){
                reInt = A0(m-1, A0(m,n-1));
           }
    }
    saveInReturnTable(m,n,reInt);
    return reInt;
} else return reInt;
}

Из комментария:

В основном у меня есть блок try-catch для перехвата любого исключения try{} catch(...){}. Насколько я понимаю, три периода должны поймать любое выброшенное исключение. И, как я понимаю, ключевое слово throw выдает исключение без каких-либо спецификаторов, но все же может быть поймано тремя точками.

Ответы [ 2 ]

4 голосов
/ 28 сентября 2011

Ошибка сегментации не является исключением C ++. Это указывает на программный сбой, который заставляет ОС отправлять сигнал SIGSEGV вашему процессу. Вы не сможете напрямую catch сигнал SIGSEGV; вам нужно настроить обработчик сигнала и ... ну, в этот момент он становится сложным, потому что не ясно, что вы можете выбросить исключение из обработчика сигнала.

A throw без указания исключения сбрасывает текущее исключение; это имеет смысл только внутри блока catch.

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

Если бы ошибка была из-за того, что calloc() не мог выделить память, вы не получили бы ошибку сегментации; вы получите нулевое возвращаемое значение. И вы можете генерировать исключение «нехватка памяти» чисто и синхронно, когда это происходит. Но это не твоя проблема.

1 голос
/ 28 сентября 2011

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

Ошибка сегментации всегда является ошибкой программирования, так или иначе, и вы должны просто ее избежать.В C ++ вы можете просто перехватывать исключения, возникающие при динамическом распределении:

 T * p;
 try { p = new T; }
 catch(const std::bad_alloc & e) { /* ... */ }

Обычно нет необходимости быть достаточно ручным, поскольку вы бы обернули свои динамические выделения в подходящие управляющие контейнеры (например, * 1008).* или shared_ptr), и вы должны ловить исключения (даже не только выделения) в тех точках потока вашей программы, где вы можете обработать ошибку и продолжать многозначительно.

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


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

// Method #1, the C++ way:
void * addr = ::operator new(n);  // will throw std::bad_alloc on error

// Method #2, the manual way:
void * addr = std::malloc(n);
if (!addr) throw std::bad_alloc();  // throw exception manually, handled elsewhere
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...