編譯程序錯誤 C2956
將會選擇一般解除配置函式 'function' 作為位置解除配置函式。
為放置新表達式找到的解除分配函式符合其中一個一般解除分配函式。 隱含編譯程式產生的解除分配或明確 delete
(或 delete[]
) 會使用錯誤的解除分配函式。
備註
錯誤 C2956 表示您使用了放置新運算式(new
採用參數的運算式),其方式可能會導致記憶體流失或運行時間當機。 這通常表示無法以一般方式刪除產生的值。 也就是說,在您的程式代碼中是明確的 delete
(或 delete[]
) 表示式,或建構函式擲回例外狀況時隱含解除分配,可能會叫用錯誤 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 中,您可以定義 operator new
多載,該多載會採用 類別中的額外 size_t
參數,將值傳遞至配置器。 在 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
,請參閱 對齊方式。
如果您的意圖是針對堆積配置的原生類型或陣列指定過度對齊的記憶體,請將它包裝在 具有規範的 alignas
或 class
中struct
。 然後,一般 new
和 delete
表達式可以配置並解除分配具有您預定對齊方式的實例。
範例
在此範例中,會 new-expression
使用 placement 語法搭配 類型的 std::align_val_t
自變數。 不過,由於類型 T
未指定對齊需求, delete-expression
所以 上的 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)
}