Erro do compilador C2956
A função de desalocação usual 'function' seria escolhida como uma função de desalocação de posicionamento.
A função de desalocação encontrada para a nova expressão de posicionamento corresponde a uma das funções de desalocação usuais. Uma desalocação gerada por compilador implícito ou explícita delete
(ou delete[]
) usaria a função de desalocação errada.
Comentários
O erro C2956 indica que você usou uma nova expressão de posicionamento (uma expressão new
que usa parâmetros) de uma maneira que pode causar um vazamento de memória ou uma falha de runtime. Normalmente, isso significa que o valor resultante não pode ser excluído de maneira típica. Ou seja, uma expressão explícita delete
(ou delete[]
) em seu código, ou a desalocação implícita quando um construtor lança uma exceção, pode invocar o operator delete
errado ou fornecê-lo com os parâmetros errados.
O padrão C++ especifica funções de desalocação habituais como sobrecargas de operator delete
ou operator delete[]
que utilizam parâmetros extras de tipo std::size_t
(C++14 ou posterior), std::align_val_t
(C++17 ou posterior) e std::destroying_delete_t
(C++20 ou posterior). Quando você usa uma nova expressão de posicionamento, o compilador procura uma função operator delete
correspondente que usa os mesmos parâmetros (após o primeiro). Se um for encontrado e sua assinatura corresponder a uma função de desalocação usual, o compilador relatará o erro C2956.
A maneira de resolver o problema depende, em parte, de sua intenção. Por exemplo, no C++11, você pode definir uma operator new
sobrecarga que usa um parâmetro extra size_t
em sua classe para passar um valor para o alocador. No C++14, o mesmo código agora causa um erro:
#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 sua intenção é especificar memória alinhada demais para um objeto, em vez disso, você pode especificar o alinhamento diretamente no tipo usando alignas
. Para obter mais informações sobre alinhamento,alignas
confira Alinhamento.
Se sua intenção for especificar memória excessivamente alinhada para um tipo nativo alocado por heap ou uma matriz, embrulhe-a em um struct
ou class
que tenha o especificador alignas
. Em seguida, as expressões normais new
e delete
podem alocar e desalocar instâncias que têm o alinhamento pretendido.
Exemplo
Neste exemplo, o new-expression
usa a sintaxe de posicionamento com um argumento do tipo std::align_val_t
. No entanto, como o tipo T
não especifica um requisito de alinhamento, um delete-expression
em um T*
não invocará uma função de desalocação alinhada demais correspondente. Em vez disso, o compilador invocaria a função de desalocação usual void operator delete(void* ptr) noexcept
, que não lida com uma alocação excessivamente alinhada. Em vez de causar uma falha ou um vazamento de memória, o compilador relata um erro para esse uso de posicionamento 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 esse problema, aplique um 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)
}