【方輝專欄】ARM嵌入式編譯器(七) C/C++的堆棧使用
2022-08-22
摘要: 本文主要對C/C++的堆棧使用進行介紹。關鍵字:堆棧、堆棧的預估1. C/C++中的堆棧在C和C++都會使用到堆棧。例如:函數(shù)的返回地址。Arm 架構的過程調用標準(AAPCS) 或Arm 64 位架構的過程調用標準(AAPCS64) 必要的寄存器。例如,當進入子程序時寄存器內容需要被保存。局部變量,包括局部數(shù)組、結構體和聯(lián)合體。C++ 中的類。一些堆棧的使用并不明顯,例如:如果局部整數(shù)或浮點變量被溢出(即未分配給寄存器),則為它們分配堆棧內存。結構體通常分配給堆棧。在堆棧上保留相當于填充多個字節(jié)的空間,其中用于AArch64 狀態(tài)或AArch32 狀態(tài)。但是,編譯器可能會嘗試將結構體分配給寄存器。 sizeof(struct)nn168如果在編譯時知道數(shù)組的大小,則編譯器會在堆棧上分配內存。同樣,在堆棧上保留了相當于填充 {n} 個字節(jié)的倍數(shù)的空間,其中用于AArch64 狀態(tài)或AArch32 狀態(tài)。 sizeof(array)n1682. 估計堆棧的使用堆棧的使用量很難估計,因為它取決于代碼的編寫,并且在運行時可能會有所不同,具體取決于程序執(zhí)行時所采用的代碼路徑。但是,可以使用以下方法手動估計堆棧利用率:編譯-g并鏈接--callgraph以生成靜態(tài)調用圖。此調用圖顯示所有函數(shù)的信息,包括堆棧使用情況。鏈接或列出所有全局符號的堆棧使用情況。--info=stack--info=summarystack使用調試器在堆棧中的最后一個可用位置設置觀察點,并查看觀察點是否被命中。使用選項編譯-g以生成必要的 DWARF 信息。注: Debugging With Attributed Record Formats(DWARF)使用帶屬性的記錄格式進行調試。利用調試器:1)為比您預期需要的大得多的堆棧分配內存空間。2)用已知值的副本填充堆??臻g,例如0xDEADDEAD.3)運行您的應用程序,并在測試中使用盡可能多的堆??臻g。例如,嘗試執(zhí)行最深嵌套的函數(shù)調用和靜態(tài)分析發(fā)現(xiàn)的最壞情況路徑。嘗試在適當?shù)牡胤缴芍袛?,以便將它們包含在堆棧跟蹤中?)應用程序完成執(zhí)行后,檢查內存的堆棧空間以查看有多少已知值已被覆蓋。該空間在已使用的部分中有數(shù)據(jù),在剩余部分中是已知值。5)計算有數(shù)據(jù)值的數(shù)量(以字節(jié)為單位)。sizeof(value)使用與目標處理器或架構相對應的固定虛擬平臺 (FVP)。使用映射文件,在堆棧正下方定義一個禁止訪問的內存區(qū)域。如果堆棧溢出到禁止區(qū)域,則會發(fā)生數(shù)據(jù)中止,調試器可以捕獲該異常。3. 檢查堆棧的使用檢查程序中函數(shù)使用堆棧的大小是一個良好的編程習慣。這樣可以寫出使用較小堆棧的代碼。要檢查程序中的堆棧使用情況,需要使用--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顯示了各種函數(shù)使用的堆棧數(shù)量。Function foo_mor比 function foo 有更多的參數(shù),因此使用更多的堆棧。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,其中包含應用程序中各種函數(shù)的堆棧使用信息。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)編寫只需要幾個變量的小函數(shù)。2)避免使用較大的局部結構體或數(shù)組3)避免遞歸調用4)函數(shù)在執(zhí)行的任何特定時候都盡可能少的使用變量。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)是國內資深的研發(fā)工具軟件提供商,公司成立于 2002 年,面向中國廣大的制造業(yè)客戶提供研發(fā)、設計、管理過程中使用的各種軟件開發(fā)工具,致力于幫助客戶提高研發(fā)管理效率、縮短產品設計周期,提升產品可靠性。20 年來,先后與 Altium、ARM、Ansys、QT、Adobe、Visu-IT、Minitab、Testplant、EPLAN、HighTec、GreenHills、PLS、Ashling、MSC Software 、Autodesk、Source Insight、TeamEDA、MicroFocus等多家全球知名公司建立戰(zhàn)略合作伙伴關系,并作為他們在中國區(qū)的主要分銷合作伙伴服務了數(shù)千家中國本土客戶,為客戶提供從芯片級開發(fā)工具、EDA 設計工具、軟件編譯以及測試工具、結構設計工具、仿真工具、電氣設計工具、以及嵌入式 GUI 工具等等。億道電子憑借多年的經驗積累,真正的幫助客戶實現(xiàn)了讓研發(fā)更簡單、更可靠、更高效的目標。歡迎關注“億道電子”公眾號了解更多研發(fā)工具軟件知識
查看更多→