【方輝專欄】ARM嵌入式編譯器(七) C/C++的堆棧使用
2022-08-22
摘要: 本文主要對C/C++的堆棧使用進行介紹。關鍵字:堆棧、堆棧的預估1. C/C++中的堆棧在C和C++都會使用到堆棧。例如:函數的返回地址。Arm 架構的過程調用標準(AAPCS) 或Arm 64 位架構的過程調用標準(AAPCS64) 必要的寄存器。例如,當進入子程序時寄存器內容需要被保存。局部變量,包括局部數組、結構體和聯合體。C++ 中的類。一些堆棧的使用并不明顯,例如:如果局部整數或浮點變量被溢出(即未分配給寄存器),則為它們分配堆棧內存。結構體通常分配給堆棧。在堆棧上保留相當于填充多個字節的空間,其中用于AArch64 狀態或AArch32 狀態。但是,編譯器可能會嘗試將結構體分配給寄存器。 sizeof(struct)nn168如果在編譯時知道數組的大小,則編譯器會在堆棧上分配內存。同樣,在堆棧上保留了相當于填充 {n} 個字節的倍數的空間,其中用于AArch64 狀態或AArch32 狀態。 sizeof(array)n1682. 估計堆棧的使用堆棧的使用量很難估計,因為它取決于代碼的編寫,并且在運行時可能會有所不同,具體取決于程序執行時所采用的代碼路徑。但是,可以使用以下方法手動估計堆棧利用率:編譯-g并鏈接--callgraph以生成靜態調用圖。此調用圖顯示所有函數的信息,包括堆棧使用情況。鏈接或列出所有全局符號的堆棧使用情況。--info=stack--info=summarystack使用調試器在堆棧中的最后一個可用位置設置觀察點,并查看觀察點是否被命中。使用選項編譯-g以生成必要的 DWARF 信息。注: Debugging With Attributed Record Formats(DWARF)使用帶屬性的記錄格式進行調試。利用調試器:1)為比您預期需要的大得多的堆棧分配內存空間。2)用已知值的副本填充堆??臻g,例如0xDEADDEAD.3)運行您的應用程序,并在測試中使用盡可能多的堆??臻g。例如,嘗試執行最深嵌套的函數調用和靜態分析發現的最壞情況路徑。嘗試在適當的地方生成中斷,以便將它們包含在堆棧跟蹤中。4)應用程序完成執行后,檢查內存的堆棧空間以查看有多少已知值已被覆蓋。該空間在已使用的部分中有數據,在剩余部分中是已知值。5)計算有數據值的數量(以字節為單位)。sizeof(value)使用與目標處理器或架構相對應的固定虛擬平臺 (FVP)。使用映射文件,在堆棧正下方定義一個禁止訪問的內存區域。如果堆棧溢出到禁止區域,則會發生數據中止,調試器可以捕獲該異常。3. 檢查堆棧的使用檢查程序中函數使用堆棧的大小是一個良好的編程習慣。這樣可以寫出使用較小堆棧的代碼。要檢查程序中的堆棧使用情況,需要使用--info=stack這個鏈接器選項。__attribute__((noinline)) int fact(int n){??int f = 1;??while (n>0)??{????f *= n--;??}??return f;}int foo (int n){??return fact(n);}int foo_mor (int a, int b, int c, int d){?return fact(a);}int main (void){??return foo(10) + foo_mor(10,11,12,13);}將代碼示例復制到file.c并使用以下命令對其進行編譯:armclang --target=arm-arm-none-eabi -march=armv8-a -c -g file.c -o file.o使用該選項進行編譯會-g生成armlink估計堆棧使用所需的 DWARF 幀信息。使用以下命令在目標文件上運行armlink:--info=stackarmlink file.o --info=stack對于示例代碼,armlink顯示了各種函數使用的堆棧數量。Function foo_mor比 function foo 有更多的參數,因此使用更多的堆棧。Stack Usage for fact 0xc bytes.Stack Usage for foo 0x8 bytes.Stack Usage for foo_mor 0x10 bytes.Stack Usage for main 0x8 bytes.您還可以使用鏈接器選項檢查堆棧使用情況--callgraph:armlink file.o --callgraph -o FileImage.axf這會輸出一個名為的文件FileImage.htm,其中包含應用程序中各種函數的堆棧使用信息。fact (ARM, 84 bytes, Stack size 12 bytes, file.o(.text))[Stack]Max Depth = 12Call Chain = fact[Called By]>> ??foo_mor>> ??foofoo (ARM, 36 bytes, Stack size 8 bytes, file.o(.text))[Stack]Max Depth = 20Call Chain = foo >> fact[Calls]>> ??fact[Called By]>> ??mainfoo_mor (ARM, 76 bytes, Stack size 16 bytes, file.o(.text))[Stack]Max Depth = 28Call Chain = foo_mor >> fact[Calls]>> ??fact[Called By]>> ??mainmain (ARM, 76 bytes, Stack size 8 bytes, file.o(.text))[Stack]Max Depth = 36Call Chain = main >> foo_mor >> fact[Calls]>> ??foo_mor>> ??foo[Called By]>> ??__rt_entry_main (via BLX)4. 減少堆棧的使用的方法減少堆棧使用量通常有以下幾個方法:1)編寫只需要幾個變量的小函數。2)避免使用較大的局部結構體或數組3)避免遞歸調用4)函數在執行的任何特定時候都盡可能少的使用變量。5)使用C塊作用域語法并在需要的位置聲明變量,這樣可以在不同作用域使用相同內存。來源:《Arm? Compiler for Embedded User Guide Version 6.18》參考鏈接:DWARF 格式簡介 https://gohalo.me/post/program-c-gdb-dwarf-format-introduce.html+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++關于億道電子億道電子技術有限公司(英文名稱:Emdoor Electronics Technology Co.,Ltd)是國內資深的研發工具軟件提供商,公司成立于 2002 年,面向中國廣大的制造業客戶提供研發、設計、管理過程中使用的各種軟件開發工具,致力于幫助客戶提高研發管理效率、縮短產品設計周期,提升產品可靠性。20 年來,先后與 Altium、ARM、Ansys、QT、Adobe、Visu-IT、Minitab、Testplant、EPLAN、HighTec、GreenHills、PLS、Ashling、MSC Software 、Autodesk、Source Insight、TeamEDA、MicroFocus等多家全球知名公司建立戰略合作伙伴關系,并作為他們在中國區的主要分銷合作伙伴服務了數千家中國本土客戶,為客戶提供從芯片級開發工具、EDA 設計工具、軟件編譯以及測試工具、結構設計工具、仿真工具、電氣設計工具、以及嵌入式 GUI 工具等等。億道電子憑借多年的經驗積累,真正的幫助客戶實現了讓研發更簡單、更可靠、更高效的目標。歡迎關注“億道電子”公眾號了解更多研發工具軟件知識
查看更多→