C++では引数の評価順をコンパイラが決めて良いことになっている。そのため、コンパイラ依存でメモリリークが発生する可能性がある。
int getValue(); void Process(shared_ptr<SomeObject> pt, int value);
を使って
Process(shared_ptr<SomeObject>(new SomeObject), getValue());
と呼び出すと
- getValueの呼び出し
- new SomeObjectの実行
- shared_ptrのコンストラクタの呼び出し
の評価順はコンパイラが決めることになる。この評価順によってはメモリリークが発生する可能性がある。例えば、
- new SomeObjectの実行
- getValueの呼び出し
- shared_ptrのコンストラクタの呼び出し
と評価し、getValueで例外が投げられるとnew SomeObjectで確保されたポインタを破棄できずリークしてしまう。
回避する方法方法としてはオブジェクトの生成とスマートポインタへの引き渡しを独立したステートメントで行う。
shared_ptr<SomeObject> pt(new SomeObject); Process(pt, getValue());
この場合、呼び出し順を
- new SomeObjectの実行
- shared_ptrのコンストラクタの呼び出し
- getValueの呼び出し
に固定できメモリリークを回避することができる。
参考文献
Effective C++ 第3版, スコット・メイヤーズ著