Skip to content

Commit fb52222

Browse files
joemmettColin Robertson
and
Colin Robertson
authored
Add documentation for compiler error C2956 and update error text (MicrosoftDocs#4176)
* Add documentation for compiler error C2956 and update error text * Add TOC entry * Update for grammar and my own comprehension. Sometimes, you just get carried away. This version could use some simplification. * Simplify. Address remarks, attempt simplification. Acrolinx all the things. * More updates per review Co-authored-by: Colin Robertson <corob@microsoft.com>
1 parent e923d0d commit fb52222

File tree

3 files changed

+65
-1
lines changed

3 files changed

+65
-1
lines changed
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
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+
```

docs/error-messages/compiler-errors-2/compiler-errors-c2900-through-c3499.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ The articles in this section of the documentation explain a subset of the error
7272
|[Compiler error C2953](compiler-error-c2953.md)|'*type*': class template has already been defined|
7373
|Compiler error C2954|instruction word argument not in range|
7474
|[Compiler error C2955](compiler-error-c2955.md)|'*type*': use of class template/generic requires template/generic argument list|
75-
|Compiler error C2956|sized deallocation function 'operator delete(void*, size_t)' would be chosen as placement deallocation function.|
75+
|[Compiler error C2956](compiler-error-c2956.md)|usual deallocation function '*function*' would be chosen as placement deallocation function|
7676
|[Compiler error C2957](compiler-error-c2957.md)|'*token*': invalid left delimiter: expected '<'|
7777
|[Compiler error C2958](compiler-error-c2958.md)|the left *delimiter* found at '*file*(*line_number*)' was not matched correctly|
7878
|[Compiler error C2959](compiler-error-c2959.md)|a generic class or function may not be a member of a template|

docs/error-messages/toc.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1915,6 +1915,8 @@ items:
19151915
href: compiler-errors-2/compiler-error-c2953.md
19161916
- name: Compiler error C2955
19171917
href: compiler-errors-2/compiler-error-c2955.md
1918+
- name: Compiler error C2956
1919+
href: compiler-errors-2/compiler-error-c2956.md
19181920
- name: Compiler error C2957
19191921
href: compiler-errors-2/compiler-error-c2957.md
19201922
- name: Compiler error C2958

0 commit comments

Comments
 (0)