Error del compilador C2956
La función de desasignación "function" habitual debe elegirse como función de desasignación de ubicación.
La función de desasignación encontrada para la nueva expresión de ubicación coincide con una de las funciones de desasignación habituales. Una desasignación implícita generada por el compilador o una expresión explícita delete
(o delete[]
) usarían la función de desasignación incorrecta.
Comentarios
El error C2956 indica que usó una nueva expresión de ubicación (una expresión new
que toma parámetros) de una manera que puede provocar una fuga de memoria o un bloqueo en tiempo de ejecución. Normalmente significa que el valor resultante no se puede eliminar de una manera típica. Es decir, una expresión explícita delete
(o delete[]
) en el código, o la desasignación implícita cuando un constructor produce una excepción, podría invocar una función operator delete
equivocada o proporcionarle parámetros incorrectos.
El estándar de C++ especifica funciones de desasignación habituales como sobrecargas de operator delete
o operator delete[]
que toman parámetros adicionales de tipo std::size_t
(C++14 o versiones posteriores), std::align_val_t
(C++17 o versiones posteriores) y std::destroying_delete_t
(C++20 o versiones posteriores). Cuando se usa una nueva expresión de ubicación, el compilador busca una función operator delete
coincidente que toma los mismos parámetros (después del primero). Si se encuentra una y su signatura coincide con una función de desasignación habitual, el compilador notifica el error C2956.
La forma en que resuelva este problema dependerá en parte de su intención. Por ejemplo, en C++11, podría definir una operator new
sobrecarga que tome un parámetro adicional size_t
en la clase para pasar un valor al asignador. En C++14, el mismo código ahora produce un 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
Si su intención es especificar memoria alineada en exceso para un objeto, puede especificar la alineación directamente en el tipo mediante alignas
. Para obtener más información sobre alignas
, consulte Alineación.
Si su intención es especificar memoria alineada en exceso para una matriz o un tipo nativo asignado al montón, encapsúlelo en un struct
o class
que tenga el especificador alignas
. Después, las expresiones new
y delete
normales pueden asignar y desasignar instancias que tengan la alineación prevista.
Ejemplo
En este ejemplo, new-expression
usa la sintaxis de ubicación con un argumento de tipo std::align_val_t
. Aun así, dado que el tipo T
no especifica un requisito de alineación, una delete-expression
en T*
no invocará una función de desasignación con una alineación en exceso coincidente. En su lugar, el compilador invocaría la función de desasignación void operator delete(void* ptr) noexcept
habitual, que no controla una asignación alineada en exceso. En lugar de provocar un bloqueo o una fuga de memoria, el compilador notifica un error para este uso de la colocación new
:
#include <new>
struct T {};
int main()
{
T* p = new (std::align_val_t{64}) T; // C2956
delete p; // ordinary, not over-aligned delete
}
Para resolver este problema, aplique un especificador alignas
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)
}