簡體   English   中英

沒有全球運營商的裸機

[英]Bare metal without global operator new

考慮安全軟件,通常不允許動態分配,並且不允許例外。 僅當類顯式定義運算符newdelete時才允許動態分配。 對其他類使用new運算符會導致編譯失敗。

在上述情況下導致編譯失敗的最簡單方法是刪除全局新運算符:

void* operator new(std::size_t) = delete;

一方面,這會導致標准庫產生副作用。 例如,包含<array> <new_allocator>通過<stdexcept>將包含傳播到<stdexcept> <new_allocator>使用::new運算符,即使您不想使用異常和內存分配,這也會導致構建失敗。 根據Scoot Meyers所說, <array>應該是裸機友好的。

另一方面,這會導致編譯器內置運算符出錯

src/main.cpp:91:31: error: deleted definition of 'void* operator new(std::size_t)'
 void* operator new(std::size_t) = delete;                               ^
<built-in>: note: previous declaration of 'void* operator new(std::size_t)'

有什么解決方法可以禁止::new並使用<array>嗎?

是否有任何解決方案可以全球范圍內禁止::new

如果您使用GCC和GNU LD,那么我認為您可以在鏈接器標志中添加--wrap=malloc 由於global ::new內部使用malloc() ,因此應用程序中對malloc()所有調用都將替換為__wrap_malloc() 如果未定義此功能,則鏈接將失敗。

另一個可能更簡單的選擇是添加ASSERT(DEFINED(malloc) == 0, "Dynamic allocation used!"); 到您的鏈接描述文件。 這將斷言未定義malloc()

這兩個選項都不能保護您避免重新定義global ::new來使用其他形式的全局分配。 您可以在鏈接描述文件中對全局符號::new進行相同的操作,但是名稱混亂(在此處_Znwj ),所以這有點奇怪...

無論您使用哪種編程語言:

在任何聲音裸機系統上,您只需從鏈接描述文件中完全刪除.heap段。 任何依賴動態分配的代碼都將無法鏈接。 而且您不必為不打算使用的段分配RAM。

我要強調兩件事:

  1. 如果未在代碼中找到異常,則將與異常相關的標頭包含在定義中不應打擾您。
  2. 當您禁用這些例外時,您將無法在代碼中使用它們(否則將導致編譯失敗)。 但是,它不會從標准庫中刪除對異常的使用。 標准庫可能包含模板類的預編譯版本,例如std::string (即std::basic_string<char, ...> )或std::streambuf (即std::basic_streambuf<char, ...> ),並且當您在代碼中使用它時,編譯器不會嘗試實例化模板,它只是重用帶有異常的預編譯版本。

為了更好地控制您的代碼,我強烈建議將-nostdlib編譯選項與G ++編譯器一起完全排除標准庫。 它不會阻止您使用各種模板類,例如STL中的std::array ,只會為您排除整個C ++庫和運行時。

我還建議閱讀《裸機C ++實用指南》 它可以使您對C ++裸機內部有更深入的了解。

暫無
暫無

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

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