簡體   English   中英

運算符new重載c++,處理失敗無一例外

[英]Operator new overloading c++, handling failure without exception

我正在做一個不使用異常的項目,應該保持這種狀態。 為了使用我自己的內存管理器,我重載了(覆蓋可能更正確) new 運算符。 在我的內存管理器中,如果分配失敗 - 將返回 NULL。 現在雖然 new 運算符返回了 NULL,但正在調用構造函數,然后我得到了一個段錯誤,因為我沒有分配內存。 我想要的功能是,如果 new 運算符返回 NULL,則不應調用構造函數(之后我將檢查對象是否已成功初始化)。

我希望它像這樣工作:

myObject = new object(...);
if (NULL == myObject)
    printf("error")
else
    do something

謝謝!

您需要調用new (nothrow) ,如下所示:

myObject* = new (std::nothrow) myObject(...);

然后,不是覆蓋常規operator new ,而是需要覆蓋采用std::nothrow_t 有關更多信息,請參見此處: http : //www.cplusplus.com/reference/new/nothrow/

沒有nothrow的常規operator new不應該在失敗時返回 null,而是應該拋出。 由於不允許拋出,因此不能實現這些運算符(除非在失敗時調用abort()或類似的方法)。

最后,在編譯期間完全禁用異常可能會有所幫助。 我希望那時會發現這種錯誤(我不確定)。

最終的解決方案是在 new 的函數聲明的末尾添加 'throw()'。

void* operator new (size_t size) throw()

可以在常規的 new 或 new (nothrow) 中完成。 在我的實現中,將它添加到常規 new 會導致任何“新”調用在失敗時都能夠返回 NULL 的預期效果。

還有一個選項是在編譯中使用 '--force_new_nothrow' 標志。

可以在此處找到有關兩者的更多信息

您必須手動執行此操作,即。

object * create_object(MemoryManager & mem, ...) {
   void * chunk = mem.get_memory_for_object();
   if (chunk == NULL) return NULL;
   return new (chunk) object(...); // inplace new 
}

我假設您想要提供一個自定義的、特定於類的分配函數,而不是在全局命名空間中重載 new 運算符。

tl;博士

從 C++11 開始:使用noexcept聲明您的自定義operator new並且一切正常。

void* T::operator new (size_t size) noexcept;

完整答案

雖然 John 給出的當前接受的答案提出了一個可行的解決方案,但它暗示std::nothrow標簽是必要的,沒有它就無法完成,這是錯誤的。

這個答案只是@dyp 的(正確)評論,擴展為完整答案,並附有標准中的當前引用。

C++11 標准在 [basic.stc.dynamic.allocation] 第 3 段中說:

如果使用非拋出異常規范 (15.4) 聲明的分配函數未能分配存儲,則應返回空指針。 未能分配存儲的任何其他分配函數應僅通過拋出與 std::bad_alloc (18.6.2.1) 類型的處理程序 (15.3) 匹配的類型的異常來指示失敗。

多年來,這句話已經被改寫,但在 C++14、C++17 和 C++20 中已經有了一些語義上等效的東西。 C++23 的當前工作草案在 [basic.stc.dynamic.allocation] 中有這一段:

具有非拋出異常規范 (14.5) 的分配函數通過返回空指針值指示失敗。 任何其他分配函數從不返回空指針值,並且僅通過拋出與 std::bad_alloc (17.6.4.1) 類型的處理程序 (14.4) 匹配的類型的異常 (14.2) 來指示失敗。

“非拋出異常規范”在 [except.spec] 中定義。 如果將noexcept添加為聲明的后綴,則函數具有此規范。 因此,問題中給出的代碼可以完全正常工作,但必須使用noexcept聲明自定義 new 運算符:

void* T::operator new (size_t size) noexcept;

或者,在 C++17 之前,使用throw()而不是noexcept工作,但它已在 C++11 中被棄用並在 C++20 中刪除。 這是 C++11 之前要走的路。 OP最終根據他們自己的回答使用了這個。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM