다음을 통해 공유


컴파일러 오류 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)
}