バックグラウンド
テストのために Intel IPP Cryptographic Libraries を使用しています。
それらは、もちろん直接インスタンス化できないハッシュや暗号化などの共有コンテキストに使用されるいくつかの不透明な構造体を定義します。
これらの不透明な構造体の 1 つを初期化するには、バイト サイズをクエリしてから、いくつかのバイトを動的に割り当て、構造体ポインターにキャストします。
彼らの例は次のように機能します。
int byteSize = 0;
ippsSHA256GetSize(&byteSize);
// IppsSHA256State shaCtx; // Error: incomplete type is not allowed
IppsSHA256State * shaCtx = (IppsSHA256State *)(new uint8_t[byteSize]);
// use shaCtx
delete [] (uint8_t *)shaCtx;
質問
割り当て解除について心配する必要がないように、スコープ付きポインター クラスでこれをラップする適切な方法は何ですか?
私が試したこと
デストラクタでのdeleteの呼び出しは、実際に割り当てられた配列のdelete []ではなく T 型になるため、次のことは安全ではないと思います。
boost::scoped_ptr<IppsSHA256State> ctx(
reinterpret_cast<IppsSHA256State *>(new uint8_t[byteSize])
);
私が検討した別の (簡略化された) オプションは、私自身の単純なスコープ ポインター クラスですが、そこでキャストすると、これが正しいかどうかわかりません。あいまいさがあります:
template <typename T>
class IppsScopedState
{
public:
explicit IppsScopedState(size_t byteSize)
: _ptr(reinterpret_cast<T *>(new uint8_t[byteSize]))
{}
T * get() const { return _ptr; }
~IppsScopedState(void) {
if (_ptr) delete [] reinterpret_cast<uint8_t *>(_ptr);
}
private:
T * _ptr;
//NUKE_COPYASSIGN_CONSTRUCTORS
};
最後に、上記のわずかなバリエーションを検討しました。
template <typename T>
class IppsScopedState
{
public:
explicit IppsScopedState(size_t byteSize)
: _ptr(new uint8_t[byteSize])
{}
T * get() const { return reinterpret_cast<T *>(_ptr); }
~IppsScopedState(void) {
if (_ptr) delete [] _ptr;
}
private:
uint8_t * _ptr;
//NUKE_COPYASSIGN_CONSTRUCTORS
};
どちらの場合でも、使用法は次のようになります。
IppsScopedState<IppsSHA256State> ctx(byteSize); // after querying for the byteSize, of course