[英]Bare metal without global operator new
考慮安全軟件,通常不允許動態分配,並且不允許例外。 僅當類顯式定義運算符new
和delete
時才允許動態分配。 對其他類使用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。
我要強調兩件事:
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.