Redigera

Dela via


Compiler Error C2956

usual deallocation function 'function' would be chosen as placement deallocation function

The deallocation function found for the placement new expression matches one of the usual deallocation functions. Either an implicit compiler-generated deallocation or an explicit delete (or delete[]) would use the wrong deallocation function.

Remarks

Error C2956 indicates you used a placement new expression (a new expression that takes parameters) in a way that can cause a memory leak or runtime crash. It usually means the resulting value can't be deleted in a typical way. That is, either an explicit delete (or delete[]) expression in your code, or the implicit deallocation when a constructor throws an exception, could invoke the wrong operator delete or supply it with the wrong parameters.

The C++ standard specifies usual deallocation functions as overloads of operator delete or operator delete[] that take extra parameters of type std::size_t (C++14 or later), std::align_val_t (C++17 or later), and std::destroying_delete_t (C++20 or later). When you use a placement new expression, the compiler looks for a matching operator delete function that takes the same parameters (after the first one). If one is found and its signature matches a usual deallocation function, the compiler reports error C2956.

The way to resolve the issue depends in part on your intent. For example, in C++11, you could define an operator new overload that takes an extra size_t parameter in your class to pass a value to the allocator. In C++14, the same code now causes an error:

#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

If your intent is to specify over-aligned memory for an object, you can instead specify the alignment directly on the type by using alignas. For more information about alignas, see Alignment.

If your intent is to specify over-aligned memory for a heap-allocated native type or an array, wrap it in a struct or class that has the alignas specifier. Then normal new and delete expressions can allocate and deallocate instances that have your intended alignment.

Example

In this example, the new-expression uses placement syntax with an argument of type std::align_val_t. However, since type T doesn't specify an alignment requirement, a delete-expression on a T* won't invoke a matching over-aligned deallocation function. Instead, the compiler would invoke the usual deallocation function void operator delete(void* ptr) noexcept, which doesn't handle an over-aligned allocation. Rather than cause a crash or a memory leak, the compiler reports an error for this use of placement new:

#include <new>
struct T {};

int main()
{
    T* p = new (std::align_val_t{64}) T; // C2956
    delete p; // ordinary, not over-aligned delete
}

To resolve this issue, apply an alignas specifier to 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)
}