2016-10-13 6 views
1

私はC-ポインタ用の自動削除機能を実装しました。コードはテストプログラムで動作しますが、私がGoogle Testでコードを使用すると、奇妙なことが起こります。なぜ私は理解できません。私は未定義の振る舞いで書きましたか?それとも、Googleテストが何とか干渉しますか?マクロASSERT_THATが、コメントアウトされている場合GoogleテストのRAIIメモリ破損

以下のコード、版画:

i1 = 0x8050cf0 
i2 = 0x8050d00 
got: 0x8050cf0 
got: 0x8050d00 
go delete: 0x8050cf0 
go delete: 0x8050d00 

二つのポインタが作成され、ガードは、これらのポインタを取得し、後でそれを削除します。これまでのところ正確には

マクロがアクティブである場合、結果は、いくつかの理由

i1 = 0x8054cf0 
i2 = 0x8054d00 
got: 0x8054cf0 
got: 0x8054d00 
go delete: 0x8054c01 

、コードが得いずれかを別のポインタを削除します。私は全く混乱している。問題を見つけるのを助けることができますか?

#include <iostream> 
#include <gmock/gmock.h> 

using namespace testing; 

class Scope_Guard { 
public: 
    Scope_Guard(std::initializer_list<int*> vals) 
    : vals_(vals) 
    { 
    for (auto ptr: vals_) { 
     std::cerr << "got: " << ptr << std::endl; 
    } 
    } 
    ~Scope_Guard() { 
    for (auto ptr: vals_) { 
     std::cerr << "go delete: " << ptr << std::endl; 
     delete ptr; 
    } 
    } 
    Scope_Guard(Scope_Guard const& rhs) = delete; 
    Scope_Guard& operator=(Scope_Guard rhs) = delete; 
private: 
    std::initializer_list<int*> vals_; 
}; 

TEST(Memory, GuardWorksInt) { 
    int* i1 = new int(1); 
    int* i2 = new int(2); 
    std::cerr << "i1 = " << i1 << std::endl; 
    std::cerr << "i2 = " << i2 << std::endl; 
    Scope_Guard g{i1, i2}; 

    ASSERT_THAT(1, Eq(1)); // (*) 
} 

int main(int argc, char** argv) { 
    InitGoogleTest(&argc, argv); 
    return RUN_ALL_TESTS(); 
} 

答えて

1

それは未定義の動作です:

あなたはクラスのメンバにコンストラクタ引数からstd::initializer_listをコピーしています。

std::initializer_listをコピーしても、基本要素はコピーされません。したがって、コンストラクタから離れると、vals_にはもう有効なものが含まれているという保証はありません。

メンバに代わりにstd::vectorを使用して、イニシャライザリストから構築します。

このガードの意図についてはわかりませんが、おそらくstd::unique_ptrを使用する方が簡単でしょう。

+0

「あなたが削除ptrを書いた理由は分かりませんが、そこにはありますか?」コンストラクタでも出力を得るのはコピー/ペーストエラーでした。発言をありがとう、私は質問を編集しました。 – olpa