コンパイラ エラー C2956
通常の割り当て解除関数 'function' は、配置の割り当て解除関数として選択されます
配置の新しい式で見つかった割り当て解除関数は、通常の割り当て解除関数のいずれかと一致します。 暗黙的なコンパイラによって生成された割り当て解除または明示的 delete な (または delete[]) は、間違った割り当て解除関数を使用します。
注釈
エラー C2956 は、メモリ リークまたはランタイム クラッシュを引き起こす可能性のある 方法で、配置の新しい式 ( new パラメーターを受け取る式) を使用したことを示します。 通常は、結果の値を一般的な方法で削除できないことを意味します。 つまり、コード内の明示的 delete (または) 式、または delete[]コンストラクターが例外をスローしたときの暗黙的な割り当て解除のどちらかが、間違ったパラメーターを呼び出すか、間違った operator delete パラメーターを指定する可能性があります。
C++ 標準では、通常のoperator deleteoperator delete[]割り当て解除関数を、型 std::size_t (C++14 以降)、(C++17 以降)、 std::align_val_t および std::destroying_delete_t (C++20 以降) の追加パラメーターのオーバーロードとして指定します。 配置の新しい式を使用すると、コンパイラは同じパラメーターを受け取る一致する operator delete 関数を検索します (最初の式の後)。 1 つが見つかり、そのシグネチャが通常の割り当て解除関数と一致する場合、コンパイラはエラー C2956 を報告します。
問題を解決する方法は、意図によって一部異なります。 たとえば、C++ 11 では、クラスに追加size_tのパラメーターをoperator new受け取ってアロケーターに値を渡すオーバーロードを定義できます。 C++ 14 では、同じコードでエラーが発生するようになりました。
#include <new>
struct T {
void* operator new(std::size_t, std::size_t); // Placement allocation function
void operator delete(void*, std::size_t); // now considered a usual deallocation function
};
T* p = new (0) T; // error: usual deallocation function would be chosen as placement deallocation function
オブジェクトに対して過剰にアラインメントされたメモリを指定することを目的とする場合は、代わりに 、 を使用 alignasして型に対して直接配置を指定できます。 詳細については alignas、「 配置」を参照してください。
ヒープ割り当て済みのネイティブ型または配列に対してオーバーアラインメモリを指定する場合は、指定子を持つalignasメモリまたはclass指定子でラップstructします。 その後、標準 new と delete 式は、意図したアラインメントを持つインスタンスを割り当て、割り当て解除できます。
例
この例では、型の new-expression 引数を持つ配置構文を使用します std::align_val_t。 ただし、型Tでは配置要件が指定されていないため、a のT*場合、delete-expression一致するオーバーアライン割り当て解除関数は呼び出されません。 代わりに、コンパイラは通常の割り当て解除関数 void operator delete(void* ptr) noexceptを呼び出します。これは、過剰にアラインされた割り当てを処理しません。 コンパイラは、クラッシュやメモリ リークを引き起こすのではなく、この配置 newの使用に関するエラーを報告します。
#include <new>
struct T {};
int main()
{
T* p = new (std::align_val_t{64}) T; // C2956
delete p; // ordinary, not over-aligned delete
}
この問題を解決するには、次に指定子を alignas 適用します T。
#include <new>
struct alignas(64) T {};
int main()
{
T* p = new T; // invokes ::operator new(std::size_t, std::align_val_t)
delete p; // now invokes ::operator delete(void*, std::align_val_t)
}