Destructor contains non-empty exception specification

A C++ destructor was declared with a non-empty exception specification.

The inclusion of a non-empty exception specification indicates the intention to throw an exception from a destructor, but C++ destructors should never throw exceptions. There are two reasons why C++ destructors should not throw exceptions. The first is that C++ objects can be torn down implicitly in contexts where exceptions cannot be allowed. For example, suppose you enter a block and declare an instance of an object X whose destructor will throw an exception E1. Now suppose you exit that block by throwing another exception, E2. The C++ runtime cannot execute the exception handlers for both E1 and E2, and choosing one would effectively lose the other exception. Since losing exceptions is unacceptable, the C++ runtime calls terminate() which normally kills the process immediately.

Even if an exception thrown by a destructor is successfully thrown and caught, it is still bad because it causes the application to leak memory. When an object is deleted, two things happen: first the destructor is called and second the delete operator is called. It is the delete operator that actually releases the storage. If the destructor throws an exception, the delete operator is never called so you will leak memory.

ID

Observation

Description

1

Definition

This shows where the destructor was defined

Example

          
#include <stdio.h>
#include <string.h>

class e1 {
private:
   char msg[100];
public:
   e1(char *p) {
      strncpy(msg, p, sizeof(msg));
   }
   char *tostring() { return msg; }
};

class e2 {
private:
   char msg[100];
public:
   e2(char *p) {
      strncpy(msg, p, sizeof(msg));
   }
   char *tostring() { return msg; }
};

class m {
private:
   char msg[100];
public:
   m(char *p) {
      strncpy(msg, p, sizeof(msg));
   }
   char *tostring() { return msg; }
   ~m() throw(e1)
   {
      if (msg[0] == 'h') throw e1(msg); // bad idea
   }
};

void f() {
    m myVar("help");
    throw new e2("me"); // program fails here: can't throw both e1 and e2
}

int main(int argc, char **argv)
{
    try {
        f();
    } catch (e1 e) {
        printf("caught e1; msg=%s\n", e.tostring());
    } catch (e2 e) {
        printf("caught e2; msg=%s\n", e.tostring());
    }
}
        

Copyright © 2010, Intel Corporation. All rights reserved.