Condividi tramite


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) noexceptdi 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)
}