Let's start by saying that a double delete is an undefined behaviour... and that means a behaviour which is not defined :)
Allow me to remind also that deleting a null pointer is a no-op. So no need to check on whether the pointer is null.
Without more context, the answer is that there is no portable solution.
Depending on architecture, OS, even the memory allocation library you are using, it will produce different effects and provide you with different options to detect it.
There's no guarantee that the program will crash on the second delete. It might simply corrupt the memory allocator structures in a way that will only crash after some time.
If your objective is detecting the problem, your best chance is to set up your program for capturing crashing signals (e.g. SIGABRT, SIGSEGV, SIGBUS...) and print a stack trace on the signal handler, before allowing the program to terminate/write the core file. As I said above, this might be or might not be the place of the memory corruption... but it will be the place where the memory allocator/program cannot go on any more.
That's the less invasive.
Using customized memory allocators or memory allocators with debugging options (e.g. libumem in Solaris) can help you in detecting earlier or more accurately where the problem was. The catch is that usually there's a bigger or smaller performance penalty.
If your objective is to prevent the problem... then you have to resort to best practices... For example.
- Resort to using RAII or smart pointers in general, or at least use them when you cannot safely establish the memory ownership throughout your program.
- At the very least, always remember to to set to null a pointer that you have deleted. That doesn't guarantee anything because you can always have concurrent deletes... but it helps reduce the scenarios where you could have a crash.