0

Deleting the double pointer is will cause the harmful effect like crash the program and programmer should try to avoid this as its not allowed. But sometime if anybody doing this then i how do we take care of this. As delete in C++ is noexcept operator and it'll not throw any exceptions. And its written type is also void. so how do we catch this kind of exceptions. Below is the code snippet

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";

In this case i tried to catch the exception but no success. Pleas provide your input how we'll take care of these type of scenario. thanks in advance!!!

Sandeep Sharma
  • 109
  • 1
  • 10
  • 1
    Use a `std::vector`? – Chris Drew Jun 10 '16 at 08:54
  • 1
    There is *nothing* you can do within the C++ language to handle a double delete. It is undefined behaviour; the standard "imposes no requirements". If you double delete, your code may crash (not an exception), format your hard drive, or post your browser password cache on github. – Martin Bonner supports Monica Jun 10 '16 at 09:04

4 Answers4

2

Given that the behaviour on a subsequent delete[] is undefined, there's nothing you can do, aside from writing

set = nullptr;

immediately after the first delete[]. This exploits the fact that a deletion of a nullptr is a no-op.

But really, that just encourages programmers to be sloppy.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483
2

Segmentation fault or bad memory access or bus errors cannot be caught by exception. Programmers need to manage their own memory correctly as you do not have garbage collection in C/C++.

But you are using C++, no ? Why not make use of RAII ?
Here is what you should strive to do:

  1. Memory ownership - Explicitly via making use of std::unique_ptr or std::shared_ptr and family.
  2. No explicit raw calls to new or delete. Make use of make_unique or make_shared or allocate_shared.
  3. Make use of containers like std::vector or std::array instead of creating dynamic arrays or allocating array on stack resp.
  4. Run your code via valgrind (Memcheck) to make sure there are no memory related issues in your code.

If you are using shared_ptr, you can use a weak_ptr to get access to the underlying pointer without incrementing the reference count. In this case, if the underlying pointer is already deleted, bad_weak_ptr exception gets thrown. This is the only scenario I know of when an exception will be thrown for you to catch when accessing a deleted pointer.

A code must undergo multiple level of testing iterations maybe with different sets of tools before committing.

Arunmu
  • 6,837
  • 1
  • 24
  • 46
  • we can catch the segmentation fault using SIGSEGV....plz refer the below link: http://stackoverflow.com/questions/10202941/segmentation-fault-handling – Sandeep Sharma Jun 10 '16 at 09:17
  • That's different, catching signal is not same as catching exception. Let me reword it. Thanks. Signal handler and exception handler has completely different call semantics. – Arunmu Jun 10 '16 at 09:27
  • so there is no such way that we can catch this kind of programming error, every programmer has to take care at their own level. – Sandeep Sharma Jun 10 '16 at 09:36
  • 1
    @SandeepSharma Not exactly. As written in my answer you can detect deleted pointers but at the cost of using a `shared_ptr - weak_ptr` even when you dont have shared ownership. In pure C++ code, I never had any memory leak or double free issue by making use of `unique_ptr` (most cases) or `shared_ptr` (few cases involving async operations). – Arunmu Jun 10 '16 at 09:40
  • @SandeepSharma Please, please, please never mention that again. We have enough shitty source to deal with without people starting to engage in that horrifically bad behaviour. – H. Guijt Jun 10 '16 at 10:02
  • Arunmu : thanks for your response. @H.Guijt: stackoverflow is a plate-form where we can discuss our problem if you have issue then please don't comment on people question. everybody thinks in diff ways. – Sandeep Sharma Jun 10 '16 at 10:10
  • @SandeepSharma I disagree. We have some responsibility here to help the guy (or girl) become a better programmer, and teaching them evil tricks like that is not going to help _at all_. He is much better served by learning how to do it correctly, rather than learning about an absolutely vile trick. Consider this: would you want to maintain code that employed such methods? If not, why would you tell others to write it? – H. Guijt Jun 10 '16 at 10:15
  • @H.Guijt: i agree with you but i never asked to follow any trick. i just asked i have faced this kind of problem and that why i asked is there any way to deal with these kind of problem. i am asking this because i wanna avoid these thing not to follow. – Sandeep Sharma Jun 10 '16 at 10:24
1

There is a very important concept in c++ called RAII (Resource Acquisition Is Initialisation).

This concept encapsulates the idea that no object may exist unless it is fully serviceable and internally consistent, and that deleting the object will release any resources it was holding.

For this reason, when allocating memory we use smart pointers:

#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
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142
0

I'm adding another answer here because previous answers focus very strongly on manually managing that memory, while the correct answer is to avoid having to deal with that in the first place.

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

This is it. This is enough. This gives you 100 integers to use as you like. They will be freed automatically when control flow leaves the function, whether through an exception, or a return, or by falling off the end of the function. There is no double delete; there isn't even a single delete, which is as it should be.

Also, I'm horrified to see suggestions in other answers for using signals to hide the effects of what is a broken program. If someone is enough of a beginner to not understand this rather basic stuff, PLEASE don't send them down that path.

H. Guijt
  • 3,325
  • 11
  • 16
  • I do not see any answer here suggesting to use signal handlers. Are you referring to some other answer to some other question ? – Arunmu Jun 10 '16 at 10:15
  • @Arunmu It's in the first comment under your own answer. You replied to it. – H. Guijt Jun 10 '16 at 11:45
  • `suggestions in other answers` this confused me :) `comments _under_ other answers` would have been less confusing. Sorry for the nit pick. Neither am I a native english speaker. – Arunmu Jun 10 '16 at 12:51