Errore del compilatore C2956
la funzione di deallocazione normale 'function' verrebbe scelta come funzione di deallocazione del posizionamento
La funzione deallocazione trovata per la nuova espressione di posizionamento corrisponde a una delle normali funzioni di deallocazione. Una deallocazione implicita generata dal compilatore o un esplicito delete
(o delete[]
) userebbe la funzione di deallocazione errata.
Osservazioni:
L'errore C2956 indica che è stata usata una nuova espressione di posizionamento (un'espressione new
che accetta parametri) in modo da causare una perdita di memoria o un arresto anomalo del runtime. In genere significa che il valore risultante non può essere eliminato in modo tipico. Ovvero, un'espressione esplicita delete
(o delete[]
) nel codice o la deallocazione implicita quando un costruttore genera un'eccezione, potrebbe richiamare l'errore operator delete
o fornirlo con i parametri errati.
Lo standard C++ specifica le normali funzioni di deallocazione come overload di operator delete
o operator delete[]
che accettano parametri aggiuntivi di tipo std::size_t
(C++14 o versione successiva), std::align_val_t
(C++17 o versione successiva) e std::destroying_delete_t
(C++20 o versione successiva). Quando si usa una nuova espressione di posizionamento, il compilatore cerca una funzione corrispondente operator delete
che accetta gli stessi parametri (dopo la prima). Se viene trovato e la relativa firma corrisponde a una normale funzione di deallocazione, il compilatore segnala l'errore C2956.
Il modo per risolvere il problema dipende in parte dalla finalità. Ad esempio, in C++11, è possibile definire un operator new
overload che accetta un parametro aggiuntivo size_t
nella classe per passare un valore all'allocatore. In C++14 lo stesso codice genera ora un errore:
#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
Se la finalità consiste nel specificare la memoria sovraallineare per un oggetto, è invece possibile specificare l'allineamento direttamente sul tipo usando alignas
. Per altre informazioni su alignas
, vedere Allineamento.
Se la finalità consiste nel specificare la memoria sovraallineare per un tipo nativo allocato dall'heap o una matrice, eseguirne il wrapping in un struct
oggetto o class
con l'identificatore alignas
. Quindi le espressioni normali new
e delete
possono allocare e deallocare istanze con allineamento previsto.
Esempio
In questo esempio, usa la sintassi di new-expression
posizionamento con un argomento di tipo std::align_val_t
. Tuttavia, poiché il tipo T
non specifica un requisito di allineamento, in un delete-expression
T*
oggetto non richiamerà una funzione di deallocazione sovraallineare la corrispondenza. Al contrario, il compilatore richiama la normale funzione void operator delete(void* ptr) noexcept
di deallocazione , che non gestisce un'allocazione sovraallineare. Anziché causare un arresto anomalo o una perdita di memoria, il compilatore segnala un errore per questo uso del posizionamento new
:
#include <new>
struct T {};
int main()
{
T* p = new (std::align_val_t{64}) T; // C2956
delete p; // ordinary, not over-aligned delete
}
Per risolvere questo problema, applicare un alignas
identificatore a 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)
}