Frage

Ich habe diesen Code ..

 CEngineLayer::CEngineLayer(void)
 {
    // Incoming creation of layers. Wrapping all of this in a try/catch block is
    // not helpful if logging of errors will happen.

    logger = new (std::nothrow) CLogger(this);

    if(logger == 0)
    {
     std::bad_alloc exception;
     throw exception;
    }

    videoLayer = new (std::nothrow) CVideoLayer(this);

    if(videoLayer == 0)
    {
     logger->log("Unable to create the video layer!");

     std::bad_alloc exception;
     throw exception;
    }
 }

 IEngineLayer* createEngineLayer(void)
 {
    // Using std::nothrow would be a bad idea here as catching things thrown
    // from the constructor is needed.

    try
    {
     CEngineLayer* newLayer = new CEngineLayer;

     return (IEngineLayer*)newLayer;
    }
    catch(std::bad_alloc& exception)
    {
     // Couldn't allocate enough memory for the engine layer.
     return 0;
    }
 }

Ich habe die meisten der nicht-verwandten Informationen weggelassen, aber ich denke, das Bild klar ist hier.

Ist es in Ordnung manuell ein std :: bad_alloc zu werfen, anstatt try / alle der Schicht Kreationen zu kontrollieren individuell und Protokollierung vor bad_allocs Erneutes Auslösen?

War es hilfreich?

Lösung

Sie brauchen nicht zu tun. Sie können die parameterlos Form der throw Anweisung verwenden, um die std::bad_alloc Ausnahme abzufangen, melden Sie es, dann erneut auslösen es:

logger = new CLogger(this);
try {
    videoLayer = new CVideoLayer(this);
} catch (std::bad_alloc&) {
    logger->log("Not enough memory to create the video layer.");
    throw;
}

Oder, wenn logger keine Smart-Pointer ist (was es sein soll):

logger = new CLogger(this);
try {
    videoLayer = new CVideoLayer(this);
} catch (std::bad_alloc&) {
    logger->log("Not enough memory to create the video layer.");
    delete logger;
    throw;
} catch (...) {
    delete logger;
    throw;
}

Andere Tipps

Sie einfach die Frage zu beantworten (da niemand sonst scheint es beantwortet zu haben), die C ++ 03-Standard definiert std::bad_alloc wie folgt:

namespace std {
  class bad_alloc : public exception {
  public:
    bad_alloc() throw();
    bad_alloc(const bad_alloc&) throw();
    bad_alloc& operator=(const bad_alloc&) throw();
    virtual ˜bad_alloc() throw();
    virtual const char* what() const throw();
  };
}

Da der Standard definiert einen öffentlichen Konstruktor, dann würden Sie vollkommen sicher sein und eine aus dem Code zu werfen zu konstruieren. (Jedes Objekt mit einem öffentlichen Copykonstruktor geworfen werden kann, IIRC).

Ich mache es persönlich werfen, wenn ich einige benutzerdefinierte allocator in STL-Container verwenden. Die Idee ist die gleiche interface- auch im Hinblick auf Verhaltens- zu den STL-Bibliotheken als Standard std :: allocator präsentieren zu können.

Also, wenn Sie eine benutzerdefinierte allocator haben (sagen wir, ein aus einem Speicherpool Zuteilung) und der Zuweisung zugrunde liegenden ausfällt, call „throw std :: bad_alloc“. Dass der Anrufer gewährleistet, der 99,9999% der Zeit einig STL-Container ist, wird es richtig aufstellen. Sie haben keine Kontrolle darüber, was diese STL-Implementierungen tun, wenn der Zuordner eine große Fett liefert 0- es unwahrscheinlich ist, etwas zu sein, das Sie mögen.

Ein weiteres Muster ist die Tatsache zu nutzen, dass der Logger unter RAH ist, auch:

CEngineLayer::CEngineLayer( )
 {
   CLogger logger(this); // Could throw, but no harm if it does.
   logger.SetIntent("Creating the video layer!");
   videoLayer = new CVideoLayer(this);
   logger.SetSucceeded(); // resets intent, so CLogger::~CLogger() is silent.
 }

Diese Skalen sauber, wenn es mehrere Schritte. Sie rufen .SetIntent wiederholt. Normalerweise Sie nur die letzte Absicht Zeichenfolge in CLogger::~CLogger() schreiben, aber für zusätzliche ausführliche Protokollierung Sie alle Absichten schreiben können.

BTW, in Ihrem createEngineLayer könnten Sie eine catch(...) wollen. Was passiert, wenn der Logger einen DiskFullException wirft?

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top