質問

私はこのコードを持っています。

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

私はほとんど関連していない情報のほとんどを省略しましたが、ここでは写真が明確だと思います。

すべてのレイヤー作成を個別に試してキャッチし、bad_allocsをre延する前にロギングする代わりに、手動でstd :: bad_allocを手動で投げることはできませんか?

役に立ちましたか?

解決

あなたはそれをする必要はありません。のパラメーターのない形式を使用できます throw キャッチするための声明 std::bad_alloc 例外、それを記録してから、それをrethrowします:

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

または、場合 logger スマートポインターではありません(そうあるべきです):

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

他のヒント

質問に答えるために(他の誰もそれに答えたようには見えないので)、C ++ 03標準は定義します std::bad_alloc 次のように:

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();
  };
}

標準はパブリックコンストラクターを定義しているため、コードを構築して投げるのは完全に安全です。 (パブリックコピーコンストラクターを備えたオブジェクトは、IIRCをスローできます)。

STLコンテナでカスタムアロケーターを使用している場合、私は個人的に投げます。アイデアは、デフォルトのSTD :: AllocatorとしてSTLライブラリに、動作の観点を含む同じインターフェイスを提示することです。

したがって、カスタムアロケーター(たとえば、メモリプールから割り当てられたもの)と基礎となる割り当ての失敗がある場合は、「stow std :: bad_alloc」を呼び出します。これにより、時間の99.9999%がSTLコンテナである発信者が適切にフィールドにフィールドを保証します。アロケーターが大きな脂肪0を返した場合、これらのSTL実装が何をするかを制御できません。

別のパターンは、ロガーがRAIIの対象となるという事実を使用することです。

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.
 }

複数のステップがある場合、これはきれいにスケールします。あなたはただ電話します .SetIntent 繰り返し。通常、あなたは最後の意図の文字列を書き出すだけです CLogger::~CLogger() しかし、余分な冗長ロギングの場合、すべての意図を書き出すことができます。

ところで、あなたの中に createEngineLayer あなたは欲しいかもしれません catch(...). 。ロガーがスローした場合はどうなりますか DiskFullException?

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top