2016-06-10 1 views
-1

Удаление двойного указателя приведет к пагубному эффекту, например, к сбою программы, и программист должен стараться избегать этого, поскольку его не разрешено. Но когда-нибудь, если кто-то это сделает, я как-то позабочусь об этом. Как удалить в C++ оператор noexcept, и он не будет вызывать никаких исключений. И его письменный тип также недействителен. так как мы можем отследить такие исключения. Ниже приведен фрагмент кодаКак справиться с двойным свободным сбоем в C++

class myException: public std::runtime_error 
{ 
    public: 
     myException(std::string const& msg): 
      std::runtime_error(msg) 
     { 
      cout<<"inside class \n"; 
      } 
}; 

void main() 
{ 

int* set = new int[100]; 
cout <<"memory allcated \n"; 
//use set[] 
delete [] set; 

cout <<"After delete first \n"; 
try{ 
delete [] set; 
throw myException("Error while deleting data \n"); 
} 
catch(std::exception &e) 
{ 
    cout<<"exception \n"; 
} 
catch(...) 
{ 
    cout<<"generic catch \n"; 
} 

cout <<"After delete second \n"; 

В этом случае я попытался поймать исключение, но не успех. Просьба предоставить вам информацию о том, как мы позаботимся об этих сценариях. спасибо заранее!

+1

Использовать 'std :: vector'? –

+1

Существует * ничего * вы можете сделать на языке C++ для обработки двойного удаления. Это неопределенное поведение; стандарт «не предъявляет никаких требований». Если вы удвоите удаление, ваш код может упасть (не исключение), отформатировать ваш жесткий диск или опубликовать кеш паролей браузера на github. –

ответ

2

Учитывая, что поведение на последующих delete[]является неопределенным, нет ничего, что вы можете сделать, кроме написания

set = nullptr;

сразу после первого delete[]. Это приводит к тому, что удаление nullptr является не-оператором.

Но на самом деле это просто поощряет программистов быть неаккуратными.

1

Ошибка исключения сегментации или плохой доступ к памяти или ошибки шины не могут быть исключены. Программистам необходимо правильно управлять собственной памятью, так как у вас нет сборки мусора на C/C++.

Но вы используете C++, нет? Почему бы не использовать RAII?
Вот что вы должны стремиться сделать:

  1. собственность памяти - Явное с помощью использования std::unique_ptr или std::shared_ptr и семьи.
  2. Нет явных необработанных вызовов new или delete. Используйте make_unique или make_shared или allocate_shared.
  3. Используйте контейнеры, такие как std::vector или std::array, вместо создания динамических массивов или выделения массива в стеке соответственно.
  4. Запустите свой код через valgrind (Memcheck), чтобы убедиться, что в вашем коде нет проблем с памятью.

Если вы используете shared_ptr, вы можете использовать weak_ptr, чтобы получить доступ к основному указателю без увеличения счетчика ссылок. В этом случае, если базовый указатель уже удален, генерируется исключение bad_weak_ptr. Это единственный сценарий, который я знаю о том, когда будет вызываться исключение для доступа к удаленному указателю.

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

+0

, мы можем поймать ошибку сегментации, используя SIGSEGV .... PLZ ссылается на следующую ссылку: http://stackoverflow.com/questions/10202941/segmentation-fault-handling –

+0

Это не так, как поймать сигнал не так же, как исключение catching. Позвольте мне переформулировать это. Благодарю. Обработчик сигналов и обработчик исключений имеют совершенно другую семантику вызова. – Arunmu

+0

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

1

Существует очень важное понятие в C++ под названием RAII (Инициализация ресурсов - инициализация).

Эта концепция инкапсулирует идею о том, что объект не может существовать, если он полностью не может быть исправным и внутренне непротиворечивым, и что удаление объекта приведет к освобождению любых ресурсов, которые он удерживает.

По этой причине, при выделении памяти мы используем смарт-указатели:

#include <memory> 
#include <iostream> 
#include <algorithm> 
#include <iterator> 

int main() 
{ 
    using namespace std; 

    // allocate an array into a smart pointer 
    auto set = std::make_unique<int[]>(100); 
    cout <<"memory allocated \n"; 

    //use set[] 
    for (int i = 0 ; i < 100 ; ++i) { 
     set[i] = i * 2; 
    } 

    std::copy(&set[0], &set[100] , std::ostream_iterator<int>(cout, ", ")); 
    cout << std::endl; 

    // delete the set 
    set.reset(); 

    cout <<"After delete first \n"; 

    // delete the set again 
    set.reset(); 
    cout <<"After delete second \n"; 

    // set also deleted here through RAII 
} 
0

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

void main() { 
    std::vector<int> set (100); 
    cout << "memory allocated\n"; 
    //use set 
} 

Это он. Достаточно. Это дает вам 100 целых чисел для использования по своему усмотрению. Они будут автоматически освобождаться, когда поток управления покидает функцию, будь то через исключение или возврат, или путем отказа от конца функции. Нет двойного удаления; нет даже одного удаления, что и должно быть.

Кроме того, я в ужасе вижу предложения в других ответах на использование сигналов, чтобы скрыть последствия того, что является нарушенной программой. Если кому-то достаточно новичка, чтобы не понимать этот довольно простой материал, ПОЖАЛУЙСТА, не отправляйте их по этому пути.

+0

Я не вижу здесь никакого ответа, предлагая использовать обработчики сигналов. Вы имеете в виду какой-то другой ответ на какой-то другой вопрос? – Arunmu

+0

@Arunmu Это в первом комментарии под вашим собственным ответом. Вы ответили на это. –

+0

'предложения в других ответах' это смутило меня :)' комментарии _under_ другие ответы' были бы менее запутанными. Извините за выбор нит. Я также не являюсь носителем английского языка. – Arunmu