2

Visual Studio 2012 Update 3 の C++ コンパイラで、やや目立たないが恐ろしいバグを発見したと思います。gtest を使用して単体テストを書いているときに見つけました。テストでメモリ リークが発生し始め、調査した結果、問題はコンパイラのバグに縮小されたように見えました。

Microsoft に問題を提出しました: https://connect.microsoft.com/VisualStudio/feedback/details/794722/parameter-dtor-not-called-when-overloaded-operator-involved-in-return

過去に、私は認めたくないほど多くの自分自身のバグを誤って「コンパイラのバグ」と呼んでいました。そのため、誰かが自分で問題を再現しようとする場合に備えて、ここに質問を投稿すると思いました。このコードで私自身の間違いを指摘できれば、それは非常に役に立ちます! 次のプログラムで VC++ コンパイラがデストラクタの呼び出しに失敗するのは、実際にはそうではないことを願っています。

オプティマイザーが無効になっていると問題のある動作が発生するため、オプティマイザーのバグではないことに注意してください。

このコードを gcc 4.2.1 (i686-apple-darwin11) で試したところ、期待どおりに動作しました。

プロジェクト内の単一のソース ファイルのコードは次のとおりです。

#include <string>

int instance_count= 0;

class c {
public:
    c( std::string s ) : m_s(s) { ++instance_count; }
    c( const c& other ) : m_s(other.m_s) { ++instance_count; }
    ~c() {--instance_count;}
private:
    std::string m_s;
};

class d {
public:
    d() {}
    void operator=(int) {}
};

void f( c c_ ) {
    try {}
    catch(...) { return d() = 5; }
}

int main( int argc, char* argv[] ) {
    c instance("leak");
    f(instance);
    return instance_count == 1 ? 0 : -1;
}

Visual Studio 2012 Update 3 でコンパイルするには:

  1. [ファイル] -> [新規] -> [プロジェクト...] で、[Win32 コンソール アプリケーション] を選択し、[OK] をクリックしてから [完了] をクリックします。
  2. ビルド -> 構成マネージャー -> アクティブ ソリューション プラットフォーム -> 新規...、x64 を選択し、[OK] をクリックします。
  3. メインの .cpp ファイルの内容を上記のコードに置き換えます
  4. ファイルの先頭に #include "stdafx.h" を追加するか、プリコンパイラ ヘッダーをオフにします。
  5. プログラムを実行します。終了コードが -1 であることに注意してください。0 であると予想されます。これは、32 ビットと 64 ビットの両方のビルドで再現されるようですが、私は 64 ビットに焦点を当てていました。
  6. f() の try/catch ブロックをコメント アウトします。終了コードが 0 になることに注意してください。catch() ブロックが実行されていないため、この変更が終了コードに影響する理由がわかりません。
4

1 に答える 1