|
| 1 | +--- |
| 2 | +description: "Learn more about: Compiler Error C2956" |
| 3 | +title: "Compiler Error C2956" |
| 4 | +ms.date: 04/05/2022 |
| 5 | +f1_keywords: ["C2956"] |
| 6 | +helpviewer_keywords: ["C2956"] |
| 7 | +--- |
| 8 | +# Compiler Error C2956 |
| 9 | + |
| 10 | +> usual deallocation function '*function*' would be chosen as placement deallocation function |
| 11 | +
|
| 12 | +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. |
| 13 | + |
| 14 | +## Remarks |
| 15 | + |
| 16 | +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. |
| 17 | + |
| 18 | +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. |
| 19 | + |
| 20 | +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: |
| 21 | + |
| 22 | +```cpp |
| 23 | +#include <new> |
| 24 | +struct T { |
| 25 | + void* operator new(std::size_t, std::size_t); // Placement allocation function |
| 26 | + void operator delete(void*, std::size_t); // now considered a usual deallocation function |
| 27 | +}; |
| 28 | + |
| 29 | +T* p = new (0) T; // error: usual deallocation function would be chosen as placement deallocation function |
| 30 | +``` |
| 31 | +
|
| 32 | +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](../../cpp/alignment-cpp-declarations.md). |
| 33 | +
|
| 34 | +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. |
| 35 | +
|
| 36 | +## Example |
| 37 | +
|
| 38 | +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`: |
| 39 | +
|
| 40 | +```cpp |
| 41 | +#include <new> |
| 42 | +struct T {}; |
| 43 | +
|
| 44 | +int main() |
| 45 | +{ |
| 46 | + T* p = new (std::align_val_t{64}) T; // C2956 |
| 47 | + delete p; // ordinary, not over-aligned delete |
| 48 | +} |
| 49 | +``` |
| 50 | + |
| 51 | +To resolve this issue, apply an `alignas` specifier to `T`: |
| 52 | + |
| 53 | +```cpp |
| 54 | +#include <new> |
| 55 | +struct alignas(64) T {}; |
| 56 | + |
| 57 | +int main() |
| 58 | +{ |
| 59 | + T* p = new T; // invokes ::operator new(std::size_t, std::align_val_t) |
| 60 | + delete p; // now invokes ::operator delete(void*, std::align_val_t) |
| 61 | +} |
| 62 | +``` |
0 commit comments