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