컴파일러 오류 C2956
일반적인 할당 취소 함수 'function'는 배치 해제 함수로 선택됩니다.
배치 새 식에 대해 찾은 할당 취소 함수는 일반적인 할당 취소 함수 중 하나와 일치합니다. 암시적 컴파일러 생성 할당 취소 또는 명시적 delete
(또는 delete[]
)은 잘못된 할당 취소 함수를 사용합니다.
설명
오류 C2956은 메모리 누수 또는 런타임 충돌을 일으킬 수 있는 방식으로 배치 새 식(new
매개 변수를 사용하는 식)을 사용했음을 나타냅니다. 일반적으로 결과 값은 일반적인 방식으로 삭제할 수 없음을 의미합니다. 즉, 코드의 명시적 delete
(또는 delete[]
) 식 또는 생성자가 예외를 throw할 때의 암시적 할당 취소는 잘못된 operator delete
매개 변수를 호출하거나 잘못된 매개 변수를 제공할 수 있습니다.
C++ 표준은 일반적인 할당 취소 함수를 오버로드 operator delete
로 지정하거나 operator delete[]
형식 std::size_t
의 추가 매개 변수(C++14 이상), std::align_val_t
(C++17 이상) 및 std::destroying_delete_t
(C++20 이상)을 사용합니다. 배치 새 식을 사용하는 경우 컴파일러는 동일한 매개 변수를 사용하는 일치하는 operator delete
함수를 찾습니다(첫 번째 식 이후). 해당 서명이 일반적인 할당 취소 함수와 일치하는 경우 컴파일러는 오류 C2956을 보고합니다.
문제를 해결하는 방법은 의도에 따라 부분적으로 달라집니다. 예를 들어 C++11에서는 클래스의 추가 size_t
매개 변수를 사용하여 할당자에 값을 전달하는 오버로드를 정의 operator new
할 수 있습니다. C++14에서 동일한 코드로 인해 오류가 발생합니다.
#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
개체에 대해 지나치게 정렬된 메모리를 지정하려는 경우 대신 .을 사용하여 alignas
형식에 직접 맞춤을 지정할 수 있습니다. 자세한 alignas
내용은 맞춤을 참조 하세요.
힙 할당 네이티브 형식 또는 배열에 대해 과도하게 정렬된 메모리를 지정하려는 경우 지정자가 있는 메모리를 래 struct
핑합니다 class
alignas
. 그런 다음, 정규 new
식과 delete
식은 의도한 맞춤이 있는 인스턴스를 할당하고 할당 취소할 수 있습니다.
예시
이 예제 new-expression
에서는 형식 std::align_val_t
의 인수와 함께 배치 구문을 사용합니다. 그러나 형식 T
은 맞춤 요구 사항을 delete-expression
지정하지 않으므로 a에서는 T*
일치하는 과잉 정렬 할당 취소 함수를 호출하지 않습니다. 대신 컴파일러는 과도하게 정렬된 할당을 처리하지 않는 일반적인 할당 취소 함수 void operator delete(void* ptr) noexcept
를 호출합니다. 컴파일러는 크래시 또는 메모리 누수의 원인이 아니라 다음과 같은 배치 new
사용에 대한 오류를 보고합니다.
#include <new>
struct T {};
int main()
{
T* p = new (std::align_val_t{64}) T; // C2956
delete p; // ordinary, not over-aligned delete
}
이 문제를 해결하려면 다음에 지정자를 alignas
적용합니다 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)
}