0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

C++ ATL 14.00 CComHeapPtr<T>は譲渡非対応→対処クラス

Last updated at Posted at 2020-06-07

ATL (Active Template Library) version 14.00のATL::CComHeapPtr<T>は譲渡非対応です。関数の戻り値に指定すると通常はコピーコンストラクタが存在しないのでコンパイルエラーが発生しますが、なぜかエラーが発生せずに保持するメモリを解放してダングリングポインタを持つコピーを返すことがありました。

同じATLクラス、それもATL::CComHeapPtr<T>の基底クラスであるATL::CHeapPtr<T>は非const参照のコピーコンストラクタによる譲渡を実装しているため気づくまで時間がかかりました。

現状のATL::CComHeapPtr<T>はバグの原因となるため、非const参照のコピーコンストラクタおよびムーブコンストラクタを実装した次のCComHeapPtr2<T>の使用を推奨します。

# include <atlbase.h>

using namespace ATL;

// CComHeapPtrに非const参照のコピーコンストラクタとムーブコンストラクタを追加したクラス
template <typename T>
class CComHeapPtr2 :
    public CHeapPtr<T, CComAllocator>
{
public:
    CComHeapPtr2() throw()
    {
    }

    explicit CComHeapPtr2(T* pData) throw()
        : CHeapPtr<T, CComAllocator>(pData)
    {
    }

    CComHeapPtr2(CComHeapPtr2& p)
        : CHeapPtr<T, CComAllocator>(p)
    {
    }

    CComHeapPtr2(CComHeapPtr2&& p)
        : CHeapPtr<T, CComAllocator>(p)
    {
    }
};
  • ムーブコンストラクタがない場合、STLコンテナクラス(std::vectorstd::list)のpush_backでconst参照のコピーコンストラクタが見つからずに想定外の動作が発生します(ないはずのconst参照のコピーコンストラクタが呼び出されてダングリングポインタが発生します)。push_backはムーブコンストラクタに対応しているため、ムーブコンストラクタを定義すればstd::moveでそちらを呼び出せます。
    • IShellFolderEnumObjectsで取得したLPITEMIDLISTを管理するときに上記のバグが起こると大惨事です。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?