SlideShare una empresa de Scribd logo
1 de 144
Descargar para leer sin conexión
例外安全入門
   @hotwatermorning
自己紹介

●
    @hotwatermorning
●
    はてなid:heisesswasser
●
    大学生
●
    DTMやってます
●
    C++が好きです
●
    「プログラミングの魔導少女」では
    「RangeとPStade.Oven」という記事を書かせ
    ていただきました。
C++erなら
誰しもメモリーリークに
悩まされたことがあるはず
今回のセッションは
その悩みを
軽減する
軽減する
  かもしれない
本日のレシピ

1.例外安全とは?
2.例外安全性の種類
3.例外安全なコードを書くには
4.例外安全にするための技法
本日のレシピ

1.例外安全とは?
2.例外安全性の種類
3.例外安全なコードを書くには
4.例外安全にするための技法

いわゆる、エラーハンドリング/例外ハンドリング関連の内容
●

は含んでおりません。
本日のレシピ

1.例外安全とは?
2.例外安全性の種類
3.例外安全なコードを書くには
4.例外安全にするための技法
● いわゆる、エラーハンドリング/例外ハンドリング関連の内容
は含んでおりません。
●
  というかそれは僕も知りたいので誰か教えt(ry
1.例外安全とは?
例外安全とは?

「あるコード内を実行中の失敗が、メモリリー
ク、格納データの不整合、不正な出力などの有
害な効果を生じないとき、そのコード片は例外
安全であると言う。」
“例外処理”
http://ja.wikipedia.org/wiki/%E4%BE%8B
%E5%A4%96%E5%87%A6%E7%90%86
例外安全とは?

「例外安全なプログラミングとは、 例外を投げ
る可能性があるコードが実際に例外を投げた場
合に、 プログラムの状態が壊れずリソースも
リークしないように作るプログラミングのこと
を言います。 」
“例外安全なプログラミング”
http://www.kmonos.net/alang/d/2.0/exception-safe.html
例外安全とは?

●
    例外が発生しても適切に対処できるよう
    なコードを書く。
●
    適切に対処しないと・・・
     ‣   メモリリーク、リソースリーク
     ‣   中途半端な操作の完了
     ‣   デストラクタから例外が投げられる
          と・・・
例外安全でないコードの例(1)

void SampleClass::ReadData(int n)
{
    delete [] data_;
    data_ = new T[n];
    read_data(data_, n);
}
例外安全でないコードの例(1)

void SampleClass::ReadData(int n)
{
    delete [] data_;
    data_ = new T[n];    //←ここや
    read_data(data_, n);
}
例外安全でないコードの例(1)

void SampleClass::ReadData(int n)
{
    delete [] data_;
    data_ = new T[n];   //←ここや
    read_data(data_, n);//←ここで
}
例外安全でないコードの例(1)

void SampleClass::ReadData(int n)
{
    delete [] data_;
    data_ = new T[n];   //←ここや
    read_data(data_, n);//←ここで
}        //例外が投げられると...??
例外安全でないコードの例(1)

void SampleClass::ReadData(int n)
{
    delete [] data_;
    data_ = new T[n];   //←ここや
    read_data(data_, n);//←ここで
}        //例外が投げられると...??
SampleClassの状態が壊れてしまう!!
例外安全でないコードの例(2)

SampleClass2 &
    SampleClass2::operator=
        (SampleClass2 const &rhs)
{
    data1_ = rhs.data1_;
    data2_ = rhs.data2_;
    data3_ = rhs.data3_;
    data4_ = rhs.data4_;
    return *this;
}
例外安全でないコードの例(2)

SampleClass2 &
    SampleClass2::operator=
        (SampleClass2 const &rhs)
{
    data1_ = rhs.data1_;
    data2_ = rhs.data2_;//このうち
    data3_ = rhs.data3_;
    data4_ = rhs.data4_;
    return *this;
}
例外安全でないコードの例(2)

SampleClass2 &
    SampleClass2::operator=
        (SampleClass2 const &rhs)
{
    data1_ = rhs.data1_;
    data2_ = rhs.data2_;//このうち
    data3_ = rhs.data3_;//どれかで
    data4_ = rhs.data4_;
    return *this;
}
例外安全でないコードの例(2)

SampleClass2 &
    SampleClass2::operator=
        (SampleClass2 const &rhs)
{
    data1_ = rhs.data1_;
    data2_ = rhs.data2_;//このうち
    data3_ = rhs.data3_;//どれかで
    data4_ = rhs.data4_;//例外が起きたら
    return *this;
}
例外安全でないコードの例(2)

SampleClass2 &
    SampleClass2::operator=
        (SampleClass2 const &rhs)
{
    data1_ = rhs.data1_;//これはどうなる?
    data2_ = rhs.data2_;//このうち
    data3_ = rhs.data3_;//どれかで
    data4_ = rhs.data4_;//例外が起きたら
    return *this;
}
例外安全なコードじゃないと
例外が起きたときに
きちんと対処できない
よし、
例外安全なコードを書こう!
と、そのまえに
2.例外安全性の種類
例外安全性の種類

●
  例外を投げない保証     高
●
  強い例外安全
              例外安全性
●
  基本的な例外安全
●
  例外安全保証なし      低
例外安全性の種類

●
  例外を投げない保証
●
  強い例外安全
              但し・・・
●
  基本的な例外安全
●
  例外安全保証なし
例外安全性の種類

●
  例外を投げない保証     高
●
  強い例外安全
               コスト…
●
  基本的な例外安全
●
  例外安全保証なし      低
例外安全性の種類

●
    例外安全保証なし
例外安全性の種類

       ●
           例外安全保証なし
●
    その関数や呼び出し先で例外が起きると
    リソースがリークしてしまうかもしれな
    い・・・
例外安全性の種類

       ●
           例外安全保証なし
void SampleClass::ReadData(int n)
{
    delete [] data_;
    data_ = new T[n];
    read_data(data_, n);
}
例外安全性の種類

●
    基本的な例外安全の保証
例外安全性の種類

     ●
         基本的な例外安全の保証
●
    例外が投げられても、いかなるリソース
    もリークしない。
例外安全性の種類

     ●
         基本的な例外安全の保証
●
    例外が投げられても、いかなるリソース
    もリークしない。
●
    副作用は出るかもしれない(データの変
    更や出力など。)
例外安全性の種類

     ●
         基本的な例外安全の保証
●
    例外が投げられても、いかなるリソース
    もリークしない。
●
    コンテナの中で例外が発生した場合、一
    貫性は保っているが、予測可能な状態と
    は限らない。
●
    なのでその後、削除や再利用はできる。
例外安全性の種類

       ●
           基本的な例外安全の保証
void SampleClass::ReadData(int n)
{
    delete [] data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
    } catch(...) {
        delete [] data_;    data_ = 0;
    }
}
例外安全性の種類

●
    強い例外安全の保証
例外安全性の種類

      ●
          強い例外安全の保証
●
    例外が起きたなら、全ての変更は
    ロールバックされる
●
    完全な成功か、例外による完全な失
    敗かの2つの状況になる
例外安全性の種類

           ●
               強い例外安全の保証
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
    }
}
例外安全性の種類

●
    例外を投げない保証(no throw)
例外安全性の種類

    ●
        例外を投げない保証(no throw)
●
    操作は全て正しく完了されることが
    保証される。
例外安全性の種類

    ●
        例外を投げない保証(no throw)
●
    操作は全て正しく完了されることが
    保証される。
●
    例)基本データ型の代入などは例外
    が起きない
例外安全性の種類

    ●
        例外を投げない保証(no throw)
●
    操作は全て正しく完了されることが
    保証される。
●
    例)基本データ型の代入などは例外
    が起きない
●
    呼び出し先も例外を投げない保証が
    できなければならない
例外安全性の種類

●
    例外を投げない保証(no throw)
void foo()
{
    int n1 =   0x10;
    int n2 =   n1;
    int *pn1   = &n1;
    int *pn2   = pn1;
}
3.例外安全なコードを書くには
例外安全なコードを書くには

●
    ある実行パス中の例外安全性は、その工
    程で一番低いものになる。
例外安全なコードを書くには

●
    ある実行パス中の例外安全性は、その工
    程で一番低いものになる。
●
    どゆこと?
例外安全なコードを書くには

int baz() { return bar() * bar(); }
void foo()
{
    int n1 = 1;     //例外安全なコード
    int n2 = bar(); //例外安全でないコード
    int n3 = 3;     //例外安全なコード
    int n4 = baz(); //例外安全でないコード
}
例外安全なコードを書くには
(さっきの「強い例外安全」のサンプルコード)

void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
    }
}
例外安全なコードを書くには
(さっきの「強い例外安全」のサンプルコード)

void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n); //←もしこの関数が
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
    }
}
例外安全なコードを書くには
(さっきの「強い例外安全」のサンプルコード)

void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n); //←もしこの関数が
        delete [] tmp;       //例外安全じゃないと
    } catch(...) {
        delete [] data_; data_ = tmp;
    }
}
例外安全なコードを書くには
(さっきの「強い例外安全」のサンプルコード)

void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n); //←もしこの関数が
        delete [] tmp;       //例外安全じゃないと
    } catch(...) {           //ReadData関数は
        delete [] data_; d...//完全な例外安全とは
    }                        //言えなくなる
}
例外安全なコードを書くには

●
    ある実行パス中の例外安全性は、その工
    程で一番低いものになる。
●
    呼び出し先の例外安全性にも左右されて
    しまう。
例外安全なコードを書くには

●
    ある実行パス中の例外安全性は、その工
    程で一番低いものになる。
●
    呼び出し先の例外安全性にも左右されて
    しまう。
●
    プログラムの中で基本的な機能であるほ
    ど、しっかりした例外安全性を実装して
    いなければならない。(コンテナなど)
例外安全なコードを書くには

●
    ある実行パス中の例外安全性は、その工
    程で一番低いものになる。
●
    呼び出し先の例外安全性にも左右されて
    しまう。
●
    プログラムの中で基本的な機能であるほ
    ど、しっかりした例外安全性を実装して
    いなければならない。(コンテナなど)
●
    標準のコンテナは大体強い保証を満たす
例外安全なコードを書くには

●
    それぞれの関数で例外を投げうる部分と
    投げない部分を明確に分離する。
●
    本来の処理の成功を確認した時点で、例
    外を投げない部分を使って、状態の変更
    と後処理を行うようにする。
例外安全なコードを書くには

●
    例外中立について
例外安全なコードを書くには
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
    }
}
例外安全なコードを書くには
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
    }   //例外安全に書けましたね!
}
例外安全なコードを書くには
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
    }   //でもいざ例外が起きたときに
}
例外安全なコードを書くには
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
    }   //ReadDataの呼び出し元は
}       //ここで起きた例外をなにも知らない
例外安全なコードを書くには

●
    例外中立について
●
    コンテナなどで例外が起きると、その例
    外が起きるまでのコンテキストを知って
    いるのは呼び出し元だけ。
例外安全なコードを書くには

●
    例外中立について
●
    コンテナなどで例外が起きると、その例
    外が起きるまでのコンテキストを知って
    いるのは呼び出し元だけ。
●
    コンテナでは、自分の行った範囲の例外
    は安全に処理できるけど、他は無理。
例外安全なコードを書くには

●
    例外中立について
●
    コンテナなどで例外が起きると、その例
    外が起きるまでのコンテキストを知って
    いるのは呼び出し元だけ。
●
    コンテナでは、自分の行った範囲の例外
    は安全に処理できるけど、他は無理。
●
    適切に処理できるところまでは例外を正
    しく伝える。
例外安全なコードを書くには
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
    }
}
例外安全なコードを書くには
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;     //正しくはこう。
    }
}
例外安全なコードを書くには

●
    単一の関数にatomicでない複数の処理が
    あると、例外安全の強い保証をするのは
    不可能。
●
    例)std::coutに出力してからstd::cerr
    に出力
4.例外安全にするための技法
これまでのことは
いまから紹介する
2つのテクニックの
布石に過ぎなかった
布石に過ぎなかった
      \ばばーん/
例外安全にするための技法

●
    いままで説明してきたことを上手く実装
    するためのテクニック
例外安全にするための技法

●
    いままで説明してきたことを上手く実装
    するためのテクニック
●
    Swap
例外安全にするための技法

●
    いままで説明してきたことを上手く実装
    するためのテクニック
●
    Swap
●
    RAII(Resource Acquisition Is
    Initialization)
例外安全にするための技法

           ●
               Swap
●
    実体を他に作って、全て成功した
    ら、変更したいリソースとSwapする
例外安全にするための技法

           ●
               Swap
●
    実体を他に作って、全て成功した
    ら、変更したいリソースとSwapする
●
    Swapは、例外を投げない保証を必ず
    守る
例外安全にするための技法
template<typename T>
void swap(T &lhs, T &rhs)
{
    T tmp = lhs;
    lhs = rhs;
    rhs = tmp;
}
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;
    } //頑張って強い例外安全にしてるけど
}
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;
    } //ロールバック用にいろいろ書いてて
}
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;
    } //例外を投げる部分が
}
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;
    } //例外を投げない部分に囲まれて
}
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;
    } //Try-Catchも入り乱れて
}
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;
    } //ちょっと複雑・・・
}
例外安全なコードを書くには

●
    それぞれの関数で例外を投げうる部分と
    投げない部分を明確に分離する。
●
    本来の処理の成功を確認した時点で、例
    外を投げない部分を使って、状態の変更
    と後処理を行うようにする。
例外安全にするための技法

           ●
               Swap
●
    実体を他に作って、全て成功した
    ら、変更したいリソースとSwap
例外安全にするための技法

            ●
                Swap
●
    実体を他に作って、全て成功した
    ら、変更したいリソースとSwap


例外を投げうる部分
                       投げない部分
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = new T[n];     //先に確保
    try {
        read_data(tmp, n);//そいつで処理
    } catch(...) {
        delete [] tmp;
    }

    std::swap(data_, tmp);//終わったら入れ替え
    delete [] tmp;        //後処理
}
例外安全にするための技法

             ●
                 Swap
●
    例外を投げうる部分と投げない部分を明
    確に分離
●
    例外を投げる部分が成功したら例外を投
    げない部分で状態を変更
●
    ロールバック用のTry-Catchは要らなく
    なる!
例外安全にするための技法

             ●
                 Swap
●
    例外を投げうる部分と投げない部分を明
    確に分離
●
    例外を投げる部分が成功したら例外を投
    げない部分で状態を変更
●
    ロールバック用のTry-Catchは要らなく
    なる!
    (リソース管理用のは必要・・・)
例外安全にするための技法

              ●
                  Swap
●
    自作クラスでも、
    Copy-Constructableなクラスなら
    swapを実装する。
例外安全にするための技法
void SampleClass::swap(SampleClass &rhs)
{
    //標準のswap関数や
    std::swap(data_, rhs.data_);
    //それ用のswap関数などで
    other_data_.swap(rhs.other_data_);
}
例外安全にするための技法

                  ●
                      Swap
●
    自作クラスでも、
    Copy-Constructableなクラスなら
    swapを実装する。
●
    SampleClass
        (SampleClass const &rhs);
例外安全にするための技法

              ●
                  Swap
●
    自作クラスでも、
    Copy-Constructableなクラスなら
    swapを実装する。
●
    実装すると・・・
例外安全にするための技法

                    ●
                        Swap
●
    自作クラスでも、
    Copy-Constructableなクラスなら
    swapを実装する。
●
    Assignableなクラスに出来る。
●
    SampleClass &
      operator=(SampleClass const &)
例外安全にするための技法
SampleClass &
    SampleClass::operator=
        (SampleClass const &rhs)
{
    //コピーコンストラクタ
    SampleClass tmp(rhs);
    //swap
    tmp.swap(*this);
    return *this;
}
例外安全にするための技法
SampleClass &
    SampleClass::operator=
        (SampleClass const &rhs)
{
    //コピーコンストラクタ
    SampleClass tmp(rhs);
    //swap
    tmp.swap(*this);      さらにまとめて
    return *this;         書くと
}
例外安全にするための技法
SampleClass &
    SampleClass::operator=
        (SampleClass const &rhs)
{
    SampleClass(rhs).swap(*this);
    return *this;
}
例外安全にするための技法
SampleClass &
    SampleClass::operator=
        (SampleClass const &rhs)
{
    SampleClass(rhs).swap(*this);
    return *this;
}
 メンバ変数がAssignableであることを
 要求しない
例外安全にするための技法
SampleClass &
    SampleClass::operator=
        (SampleClass const &rhs)
{
    SampleClass(rhs).swap(*this);
    return *this;
}
             Copy And Swap
例外安全にするための技法

          ●
              RAII
●
    「リソースの確保は初期化である」
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;
    } //リソース管理のためにコードが複雑に
}
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;
    } //deleteも分散してしまった
}
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;
    } //対応していない
}
例外安全にするための技法

          ●
              RAII
●
    「リソースの確保は初期化である」
●
    コンストラクタでリソースを確保
●
    デストラクタでリソースを破棄
例外安全にするための技法

          ●
              RAII
●
    「リソースの確保は初期化である」
●
    コンストラクタでリソースを確保
●
    デストラクタでリソースを破棄

        対応!!
例外安全にするための技法

                    ●
                        RAII
class RAIIClass
{
    RAIIClass(Resource r) : r_(r) {}
    RAIIClass(Args as) : r_(CreateResource(as))
    {}

    ~RAIIClass() { DisposeResource(r_); }
private:
    Resource r_;
};
例外安全にするための技法

          ●
              RAII
●
    これをメモリ管理に使ったのがいわ
    ゆるスマートポインタ
例外安全にするための技法

          ●
              RAII
●
    これをメモリ管理に使ったのがいわ
    ゆるスマートポインタ
●
    プログラマはリソース解放のめんど
    くささから解放される!
例外安全にするための技法

          ●
              RAII
●
    これをメモリ管理に使ったのがいわ
    ゆるスマートポインタ
●
    プログラマはリソース解放のめんど
    くささから解放される!
●
    例外安全とか考えなくても使うべ
    き!
例外安全にするための技法

          ●
              RAII
●
    これがどのように例外安全性の点で
    重宝されるのか?
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;
    }
}
例外安全にするための技法

            ●
                RAII
●
    Deleteのために例外をCatchしなく
    ちゃいけなかった
例外安全にするための技法

            ●
                RAII
●
    Deleteのために例外をCatchしなく
    ちゃいけなかった
●
    でもRAIIなクラスを使うと、Delete
    は自動化できる
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];      これが
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
        throw;
    }
}
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    shared_array<T> tmp = data_;
    try {
        data_.reset(new T[n]); こうなる
        read_data(data_, n);
    } catch (...) {
        data_ = tmp;
    }
}
例外安全にするための技法

            ●
                RAII
●
    どこで起きるかわからないような例
    外によって関数を抜けるときも、そ
    の時に自動でリソースが解放され
    る!
●
    リソース解放のためのTry-Catchは要
    らなくなる!
例外安全にするための技法

            ●
                RAII
●
    どこで起きるかわからないような例
    外によって関数を抜けるときも、そ
    の時に自動でリソースが解放され
    る!
●
    リソース解放のためのTry-Catchは要
    らなくなる!(強い例外安全保証の
    ためのは必要・・・)
例外安全にするための技法

   ●
       SwapとRAII
例外安全にするための技法

      ●
          SwapとRAII
1.Swapはロールバック用のTry-
 Catchを不要にする。
例外安全にするための技法

      ●
          SwapとRAII
1.Swapはロールバック用のTry-
 Catchを不要にする。
2.RAIIはリソース管理用のTry-
 Catchを不要にする。
例外安全にするための技法

      ●
          SwapとRAII
1.Swapはロールバック用のTry-
 Catchを不要にする。
2.RAIIはリソース管理用のTry-
 Catchを不要にする。
3.例外中立のために、例外が起き
 てもいじらないで伝える。
例外安全にするための技法

   ●
       SwapとRAII



 合体
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    shared_array<T> tmp(new T[n]);
    read_data(tmp_, n);
    std::swap(data_, tmp);
}
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    shared_array<T> tmp(new T[n]);
    read_data(tmp_, n);
    std::swap(data_, tmp);
}

      おわかりいただけただろうか
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    shared_array<T> tmp(new T[n]);
    read_data(tmp_, n);
    std::swap(data_, tmp);
}

      おわかりいただけただろうか
      ではもう一度・・・
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    T *tmp = data_; data_ = 0;
    try {
        data_ = new T[n];
        read_data(data_, n);
        delete [] tmp;
    } catch(...) {
        delete [] data_; data_ = tmp;
    }
}
例外安全にするための技法
void SampleClass::ReadData(int n)
{
    shared_array<T> tmp(new T[n]);
    read_data(tmp_, n);
    std::swap(data_, tmp);
}
例外安全にするための技法

         ●
             SwapとRAII
●
    適切なコードを書けば、例外安全
    性のためにTry-Catchを書く必要
    はない。
例外安全にするための技法

 ●
     デストラクタで例外
例外安全にするための技法

      ●
          デストラクタで例外
●
    禁止!
例外安全にするための技法

      ●
          デストラクタで例外
●
    禁止!
●
    配列を安全にできない
●
    例外が起きたときにスタックの巻
    き戻しを安全にできない
●
    全ての例外安全の努力が水の泡!
5.まとめ
まとめ

●
    例外安全なコードを書くには
まとめ

●
    例外安全なコードを書くには
●
    例外を投げる部分と投げない部分を
    分離して、例外のある処理の成功を
    確認してから、状態を変更する。
●
    RAIIを使用してリソースの管理を自
    動化する
まとめ

●
    今回の内容はほとんど全て
    「Exceptional C++」
    (ハーブ・サッター著)
    に書かれています
●
    あと「C++ Coding Standard」も
おしまい。

Más contenido relacionado

La actualidad más candente

Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Takefumi MIYOSHI
 
Intel AVX2を使用したailia sdkの最適化
Intel AVX2を使用したailia sdkの最適化Intel AVX2を使用したailia sdkの最適化
Intel AVX2を使用したailia sdkの最適化HitoshiSHINABE1
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safeKumazaki Hiroki
 
Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説JPCERT Coordination Center
 
Visual C++コード分析を支えるSAL
Visual C++コード分析を支えるSALVisual C++コード分析を支えるSAL
Visual C++コード分析を支えるSALegtra
 
Secure scheme script suite
Secure scheme script suiteSecure scheme script suite
Secure scheme script suiteTod Morita
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„和弘 井之上
 
20130611 java concurrencyinpracticech7
20130611 java concurrencyinpracticech720130611 java concurrencyinpracticech7
20130611 java concurrencyinpracticech7Toshiaki Toyama
 
Javaコーディング勉強会
Javaコーディング勉強会Javaコーディング勉強会
Javaコーディング勉強会inatus
 
signal の話 或いは Zend Signals とは何か
signal の話 或いは Zend Signals とは何かsignal の話 或いは Zend Signals とは何か
signal の話 或いは Zend Signals とは何かdo_aki
 
4章 Linuxカーネル - 割り込み・例外 4
 4章 Linuxカーネル - 割り込み・例外 4 4章 Linuxカーネル - 割り込み・例外 4
4章 Linuxカーネル - 割り込み・例外 4mao999
 

La actualidad más candente (15)

Sharing Deep Dive
Sharing Deep DiveSharing Deep Dive
Sharing Deep Dive
 
Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512Synthesijer and Synthesijer.Scala in HLS-friends 201512
Synthesijer and Synthesijer.Scala in HLS-friends 201512
 
Intel AVX2を使用したailia sdkの最適化
Intel AVX2を使用したailia sdkの最適化Intel AVX2を使用したailia sdkの最適化
Intel AVX2を使用したailia sdkの最適化
 
冬のLock free祭り safe
冬のLock free祭り safe冬のLock free祭り safe
冬のLock free祭り safe
 
Slide
SlideSlide
Slide
 
Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説Javaセキュアコーディングセミナー東京第2回演習の解説
Javaセキュアコーディングセミナー東京第2回演習の解説
 
Visual C++コード分析を支えるSAL
Visual C++コード分析を支えるSALVisual C++コード分析を支えるSAL
Visual C++コード分析を支えるSAL
 
20180123 power shell
20180123 power shell20180123 power shell
20180123 power shell
 
Secure scheme script suite
Secure scheme script suiteSecure scheme script suite
Secure scheme script suite
 
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„
【C++BUILDER STARTER チュートリアルシリーズ】シーズン2 C++Builderの部 第1回 ‟シューティングゲームのプログラム„
 
20130611 java concurrencyinpracticech7
20130611 java concurrencyinpracticech720130611 java concurrencyinpracticech7
20130611 java concurrencyinpracticech7
 
Javaコーディング勉強会
Javaコーディング勉強会Javaコーディング勉強会
Javaコーディング勉強会
 
セキュアPHP
セキュアPHPセキュアPHP
セキュアPHP
 
signal の話 或いは Zend Signals とは何か
signal の話 或いは Zend Signals とは何かsignal の話 或いは Zend Signals とは何か
signal の話 或いは Zend Signals とは何か
 
4章 Linuxカーネル - 割り込み・例外 4
 4章 Linuxカーネル - 割り込み・例外 4 4章 Linuxカーネル - 割り込み・例外 4
4章 Linuxカーネル - 割り込み・例外 4
 

Similar a Sapporocpp#2 exception-primer

APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。Satoshi Mimura
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 TipsTakaaki Suzuki
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングKohsuke Yuasa
 
知って得するC#
知って得するC#知って得するC#
知って得するC#Shota Baba
 
SpectreBustersあるいはLinuxにおけるSpectre対策
SpectreBustersあるいはLinuxにおけるSpectre対策SpectreBustersあるいはLinuxにおけるSpectre対策
SpectreBustersあるいはLinuxにおけるSpectre対策Masami Hiramatsu
 
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)Takuya Tsuchida
 
Infer.netによるldaの実装
Infer.netによるldaの実装Infer.netによるldaの実装
Infer.netによるldaの実装池田 直哉
 
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)フリーでできるセキュリティWeb編(SQLMあpを楽しもう)
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)abend_cve_9999_0001
 
[CB19] アンチウイルスをオラクルとしたWindows Defenderに対する新しい攻撃手法 by 市川遼
[CB19] アンチウイルスをオラクルとしたWindows Defenderに対する新しい攻撃手法 by 市川遼 [CB19] アンチウイルスをオラクルとしたWindows Defenderに対する新しい攻撃手法 by 市川遼
[CB19] アンチウイルスをオラクルとしたWindows Defenderに対する新しい攻撃手法 by 市川遼 CODE BLUE
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎信之 岩永
 

Similar a Sapporocpp#2 exception-primer (12)

APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
APASEC 2013 - ROP/JIT を使わずに DEP/ASLR を回避する手法を見てみた。
 
今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips今日からできる!簡単 .NET 高速化 Tips
今日からできる!簡単 .NET 高速化 Tips
 
C++ マルチスレッドプログラミング
C++ マルチスレッドプログラミングC++ マルチスレッドプログラミング
C++ マルチスレッドプログラミング
 
知って得するC#
知って得するC#知って得するC#
知って得するC#
 
Inside FastEnum
Inside FastEnumInside FastEnum
Inside FastEnum
 
SpectreBustersあるいはLinuxにおけるSpectre対策
SpectreBustersあるいはLinuxにおけるSpectre対策SpectreBustersあるいはLinuxにおけるSpectre対策
SpectreBustersあるいはLinuxにおけるSpectre対策
 
あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)あんなテスト、こんなテスト(this and that about testing)
あんなテスト、こんなテスト(this and that about testing)
 
No.2 超初心者向け セキュリティ入門
No.2 超初心者向け セキュリティ入門No.2 超初心者向け セキュリティ入門
No.2 超初心者向け セキュリティ入門
 
Infer.netによるldaの実装
Infer.netによるldaの実装Infer.netによるldaの実装
Infer.netによるldaの実装
 
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)フリーでできるセキュリティWeb編(SQLMあpを楽しもう)
フリーでできるセキュリティWeb編(SQLMあpを楽しもう)
 
[CB19] アンチウイルスをオラクルとしたWindows Defenderに対する新しい攻撃手法 by 市川遼
[CB19] アンチウイルスをオラクルとしたWindows Defenderに対する新しい攻撃手法 by 市川遼 [CB19] アンチウイルスをオラクルとしたWindows Defenderに対する新しい攻撃手法 by 市川遼
[CB19] アンチウイルスをオラクルとしたWindows Defenderに対する新しい攻撃手法 by 市川遼
 
非同期処理の基礎
非同期処理の基礎非同期処理の基礎
非同期処理の基礎
 

Más de Kohsuke Yuasa

オーディオ用レベルメータを作ってみよう
オーディオ用レベルメータを作ってみようオーディオ用レベルメータを作ってみよう
オーディオ用レベルメータを作ってみようKohsuke Yuasa
 
Juceで作るオーディオアプリケーション
Juceで作るオーディオアプリケーションJuceで作るオーディオアプリケーション
Juceで作るオーディオアプリケーションKohsuke Yuasa
 
最近のC++ @ Sapporo.cpp #5
最近のC++ @ Sapporo.cpp #5最近のC++ @ Sapporo.cpp #5
最近のC++ @ Sapporo.cpp #5Kohsuke Yuasa
 
規格書で読むC++11のスレッド
規格書で読むC++11のスレッド規格書で読むC++11のスレッド
規格書で読むC++11のスレッドKohsuke Yuasa
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプKohsuke Yuasa
 
Introduction to boost test
Introduction to boost testIntroduction to boost test
Introduction to boost testKohsuke Yuasa
 

Más de Kohsuke Yuasa (9)

オーディオ用レベルメータを作ってみよう
オーディオ用レベルメータを作ってみようオーディオ用レベルメータを作ってみよう
オーディオ用レベルメータを作ってみよう
 
Juceで作るオーディオアプリケーション
Juceで作るオーディオアプリケーションJuceで作るオーディオアプリケーション
Juceで作るオーディオアプリケーション
 
最近のC++ @ Sapporo.cpp #5
最近のC++ @ Sapporo.cpp #5最近のC++ @ Sapporo.cpp #5
最近のC++ @ Sapporo.cpp #5
 
規格書で読むC++11のスレッド
規格書で読むC++11のスレッド規格書で読むC++11のスレッド
規格書で読むC++11のスレッド
 
C++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプC++ ポインタ ブートキャンプ
C++ ポインタ ブートキャンプ
 
Introduction to boost test
Introduction to boost testIntroduction to boost test
Introduction to boost test
 
C++ template-primer
C++ template-primerC++ template-primer
C++ template-primer
 
Read egg oven
Read egg ovenRead egg oven
Read egg oven
 
Study3 boost
Study3 boostStudy3 boost
Study3 boost
 

Último

クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfFumieNakayama
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfFumieNakayama
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?akihisamiyanaga1
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineerYuki Kikuchi
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)UEHARA, Tetsutaro
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NTT DATA Technology & Innovation
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...博三 太田
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)Hiroshi Tomioka
 

Último (8)

クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdfクラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
クラウドネイティブなサーバー仮想化基盤 - OpenShift Virtualization.pdf
 
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdfAWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
AWS の OpenShift サービス (ROSA) を使った OpenShift Virtualizationの始め方.pdf
 
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
CTO, VPoE, テックリードなどリーダーポジションに登用したくなるのはどんな人材か?
 
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
自分史上一番早い2024振り返り〜コロナ後、仕事は通常ペースに戻ったか〜 by IoT fullstack engineer
 
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
デジタル・フォレンジックの最新動向(2024年4月27日情洛会総会特別講演スライド)
 
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
NewSQLの可用性構成パターン(OCHaCafe Season 8 #4 発表資料)
 
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察  ~Text-to-MusicとText-To-ImageかつImage-to-Music...
モーダル間の変換後の一致性とジャンル表を用いた解釈可能性の考察 ~Text-to-MusicとText-To-ImageかつImage-to-Music...
 
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
業務で生成AIを活用したい人のための生成AI入門講座(社外公開版:キンドリルジャパン社内勉強会:2024年4月発表)
 

Sapporocpp#2 exception-primer