0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

嵌入式C代碼調(diào)試?yán)鱞acktrace介紹

lilihe92 ? 來源:最后一個(gè)bug ? 2023-03-08 16:55 ? 次閱讀

1

backtrace基本原理

backtrace英譯為回溯的意思,這聽起來有點(diǎn)專業(yè)了,其實(shí)大部分搞嵌入式的朋友都有聽說過函數(shù)調(diào)用棧callstack。而backtrace說白了就是我們呈現(xiàn)函數(shù)調(diào)用關(guān)系的一項(xiàng)功能。

所以backtrace調(diào)試功能的實(shí)現(xiàn)原理基于函數(shù)調(diào)用棧的概念。

那什么是函數(shù)調(diào)用棧呢?

函數(shù)調(diào)用棧是一個(gè)記錄程序中函數(shù)調(diào)用關(guān)系的數(shù)據(jù)結(jié)構(gòu),它在程序運(yùn)行時(shí)動(dòng)態(tài)生成和維護(hù)。當(dāng)程序執(zhí)行函數(shù)調(diào)用時(shí),它將當(dāng)前函數(shù)的返回地址和一些其他信息壓入堆棧中,并跳轉(zhuǎn)到被調(diào)用的函數(shù)執(zhí)行。當(dāng)被調(diào)用函數(shù)執(zhí)行完畢后,它將返回地址彈出堆棧,并跳回到調(diào)用函數(shù)繼續(xù)執(zhí)行。

backtrace調(diào)試功能的實(shí)現(xiàn)原理就是利用函數(shù)調(diào)用棧中的信息來追蹤程序執(zhí)行的路徑和調(diào)用關(guān)系。當(dāng)程序出現(xiàn)錯(cuò)誤或崩潰時(shí),backtrace可以通過分析函數(shù)調(diào)用棧信息來確定出錯(cuò)的位置和原因。

Linux系統(tǒng)中,backtrace通常是通過使用調(diào)試器比如我們常用的gdb來實(shí)現(xiàn)的。調(diào)試器會(huì)在程序執(zhí)行時(shí),動(dòng)態(tài)地獲取函數(shù)調(diào)用棧信息,并將其保存在調(diào)試器的內(nèi)部數(shù)據(jù)結(jié)構(gòu)中。當(dāng)程序出現(xiàn)錯(cuò)誤或崩潰時(shí),調(diào)試器就可以利用保存的函數(shù)調(diào)用棧信息來進(jìn)行backtrace操作。

2

backtrace功能

而對(duì)于backtrace這個(gè)功能在不同的平臺(tái)和開發(fā)環(huán)境中的使用是不同的.

比如在我們平時(shí)的linux環(huán)境中:可以使用glibc提供的backtrace()函數(shù)實(shí)現(xiàn)backtrace功能。該函數(shù)通過解析函數(shù)調(diào)用棧信息獲取函數(shù)名、參數(shù)和返回地址等信息,并將其打印到標(biāo)準(zhǔn)輸出或指定的文件中。

此外,還可以使用gdb或libunwind庫來實(shí)現(xiàn)backtrace功能。gdb是一個(gè)強(qiáng)大的調(diào)試器,可以實(shí)時(shí)追蹤程序的執(zhí)行,獲取程序的調(diào)用棧信息,并提供各種調(diào)試工具和命令。

而其中的libunwind則是一個(gè)開源的C/C++庫,也可以用于在運(yùn)行時(shí)獲取當(dāng)前程序的調(diào)用棧信息,并且在不同的平臺(tái)和架構(gòu)上運(yùn)行,并提供了簡(jiǎn)單易用的API接口,同樣也是非常方便的。

3

glibc下的backtrace功能使用

glibc提供了backtrace函數(shù),可以用來獲取當(dāng)前程序的調(diào)用棧信息,使用方法如下:

包含頭文件:

#include

定義一個(gè)數(shù)組,用于存儲(chǔ)回溯信息:

#defineBT_BUF_SIZE100
void*bt_buffer[BT_BUF_SIZE];

該數(shù)組用于存儲(chǔ)backtrace信息,數(shù)組大小可以根據(jù)需要進(jìn)行調(diào)整。

3. 調(diào)用backtrace函數(shù):

intbt_size=backtrace(bt_buffer,BT_BUF_SIZE);

該函數(shù)會(huì)獲取當(dāng)前程序的調(diào)用棧信息,并將其存儲(chǔ)在bt_buffer數(shù)組中。bt_size表示實(shí)際獲取到的調(diào)用棧信息的條數(shù),該值不會(huì)超過BT_BUF_SIZE。

4. 使用backtrace_symbols函數(shù)將backtrace信息轉(zhuǎn)換成字符串:

char**bt_strings=backtrace_symbols(bt_buffer,bt_size);

該函數(shù)將backtrace信息轉(zhuǎn)換成字符串?dāng)?shù)組,每個(gè)字符串表示一個(gè)調(diào)用棧信息。bt_strings指向字符串?dāng)?shù)組的首地址,需要在使用完畢后手動(dòng)釋放內(nèi)存。

5. 打印回溯信息:

for(inti=0;i

該代碼會(huì)將回溯信息打印到標(biāo)準(zhǔn)輸出中,可以根據(jù)需要進(jìn)行調(diào)整。完整的使用示例代碼如下:

#include
#include
#include
#defineBT_BUF_SIZE100
voidprint_backtrace(){
void*bt_buffer[BT_BUF_SIZE];
intbt_size=backtrace(bt_buffer,BT_BUF_SIZE);
char**bt_strings=backtrace_symbols(bt_buffer,bt_size);
printf("backtrace:
");
for(inti=0;i

該程序會(huì)輸出調(diào)用棧信息,格式如下:

backtrace:
./backtrace_demo(func_c+0x16)[0x40069a]
./backtrace_demo(func_b+0xd)[0x4006c5]
./backtrace_demo(func_a+0xd)[0x4006e0]
./backtrace_demo(main+0xe)[0x4006f6]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf1)[0x7f6a69e2b1c1]
./backtrace_demo(_start+0x2a)[0x400529]

其中每一行表示一個(gè)調(diào)用棧信息,格式為"函數(shù)名+偏移量+[地址]"。

4

gdb的backtrace功能

在Linux下進(jìn)行嵌入式開發(fā),backtrace通常是通過使用調(diào)試器來實(shí)現(xiàn)的,這樣的話,gdb都跟你封裝成了相應(yīng)的命令,使用起來也簡(jiǎn)單很多。

下面以gdb為例來介紹如何使用backtrace:

1、編譯程序時(shí)添加-g選項(xiàng),以在可執(zhí)行文件中包含調(diào)試信息。因?yàn)閎acktrace函數(shù)需要獲取調(diào)用棧信息,因此需要包含符號(hào)信息。如果使用了-g選項(xiàng)進(jìn)行編譯,則可以保證符號(hào)信息的完整性,如果沒有使用-g選項(xiàng)編譯程序,則可能會(huì)出現(xiàn)獲取不到符號(hào)信息的情況,導(dǎo)致backtrace函數(shù)無法正常工作。

例如,使用gcc編譯時(shí)可以添加-g選項(xiàng):

gcc-g-oprogramprogram.c
2、使用gdb啟動(dòng)程序并暫停程序的執(zhí)行。例如,可以使用以下命令啟動(dòng)程序:然后使用以下命令在程序執(zhí)行時(shí)暫停程序的執(zhí)行:這將在程序的main函數(shù)處設(shè)置斷點(diǎn),并啟動(dòng)程序的執(zhí)行。
gdbprogram
(gdb)breakmain
(gdb)run
3、當(dāng)程序崩潰或出現(xiàn)錯(cuò)誤時(shí),gdb會(huì)自動(dòng)暫停程序的執(zhí)行,并顯示當(dāng)前程序的調(diào)用棧信息??梢允褂靡韵旅畈榭凑{(diào)用棧信息:這將顯示當(dāng)前程序的調(diào)用棧信息,包括每個(gè)函數(shù)的名稱、參數(shù)和返回值等信息,以及每個(gè)函數(shù)在調(diào)用棧中的位置。
(gdb)backtrace
4、最后可以使用其他gdb命令來查看每個(gè)函數(shù)的參數(shù)和局部變量等信息,以幫助定位代碼崩潰或錯(cuò)誤的原因。

5

跟蹤的準(zhǔn)確性

在實(shí)現(xiàn)backtrace功能時(shí),還需要注意一些細(xì)節(jié)問題。例如,需要注意函數(shù)調(diào)用棧的深度和堆棧溢出等問題,以及需要保證backtrace操作的可靠性和準(zhǔn)確性,下面簡(jiǎn)單聊聊如下三個(gè)值得注意的方面:

優(yōu)化選項(xiàng):程序使用了-O選項(xiàng)進(jìn)行優(yōu)化時(shí),可能會(huì)改變函數(shù)調(diào)用棧的結(jié)構(gòu),從而使backtrace函數(shù)獲取到的信息不完整或不準(zhǔn)確。因此,在使用backtrace函數(shù)時(shí),建議關(guān)閉優(yōu)化選項(xiàng),以保證其可靠性。

棧溢出:如果程序發(fā)生棧溢出,可能會(huì)破壞調(diào)用棧信息,導(dǎo)致backtrace函數(shù)獲取到的信息不完整或不準(zhǔn)確。因此,在程序中應(yīng)該避免出現(xiàn)棧溢出的情況,以保證backtrace函數(shù)的可靠性。

線程安全:如果程序使用多線程,每個(gè)線程都有自己的調(diào)用棧,因此需要在每個(gè)線程中分別調(diào)用backtrace函數(shù)來獲取相應(yīng)的調(diào)用棧信息。此外,在多線程環(huán)境下,需要注意避免競(jìng)爭(zhēng)條件的出現(xiàn),以保證backtrace函數(shù)的可靠性。

總之,在使用glibc提供的backtrace函數(shù)時(shí),需要注意編譯選項(xiàng)、優(yōu)化選項(xiàng)、棧溢出和線程安全等因素,以保證其可靠性。此外,不同的硬件平臺(tái)和操作系統(tǒng)可能有不同的backtrace實(shí)現(xiàn)方式和接口,需要使用相應(yīng)的工具和API來實(shí)現(xiàn)。





審核編輯:劉清

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 嵌入式
    +關(guān)注

    關(guān)注

    5060

    文章

    18979

    瀏覽量

    302235
  • Linux系統(tǒng)
    +關(guān)注

    關(guān)注

    4

    文章

    590

    瀏覽量

    27320
  • 調(diào)試器
    +關(guān)注

    關(guān)注

    1

    文章

    300

    瀏覽量

    23669
  • API接口
    +關(guān)注

    關(guān)注

    1

    文章

    82

    瀏覽量

    10420
  • GDB調(diào)試
    +關(guān)注

    關(guān)注

    0

    文章

    24

    瀏覽量

    1432

原文標(biāo)題:嵌入式C代碼調(diào)試?yán)?--backtrace

文章出處:【微信號(hào):最后一個(gè)bug,微信公眾號(hào):最后一個(gè)bug】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。

收藏 人收藏

    評(píng)論

    相關(guān)推薦

    嵌入式程序基于源代碼仿真調(diào)試

    前面一課設(shè)計(jì)了51單片機(jī)最小系統(tǒng)電路,使用51單片機(jī)的I/O口控制發(fā)光二極管的狀態(tài),并裝載運(yùn)行了使用keil編寫的嵌入式程序。本次實(shí)驗(yàn)應(yīng)用proteus結(jié)合keil對(duì)嵌入式C程序進(jìn)行源代碼
    的頭像 發(fā)表于 11-01 09:24 ?1124次閱讀
    <b class='flag-5'>嵌入式</b>程序基于源<b class='flag-5'>代碼</b>仿真<b class='flag-5'>調(diào)試</b>

    如何調(diào)試嵌入式代碼?

    我們?cè)谶M(jìn)行嵌入式系統(tǒng)開發(fā)調(diào)試時(shí),受限于嵌入式芯片資源和性能,一般采用遠(yuǎn)程調(diào)試。在調(diào)試嵌入式底層
    發(fā)表于 12-17 06:32

    嵌入式實(shí)時(shí)程序設(shè)計(jì)中C/C++代碼的優(yōu)化

    本文簡(jiǎn)單介紹嵌入式實(shí)時(shí)程序設(shè)計(jì)的特點(diǎn)和嵌入式系統(tǒng)設(shè)計(jì)中語言的選擇,著重介紹了以下幾種在嵌入式實(shí)時(shí)程序設(shè)計(jì)中優(yōu)化
    發(fā)表于 08-07 08:47 ?15次下載

    嵌入式程序設(shè)計(jì)中C/C++代碼的優(yōu)化

    本文介紹了在嵌入式程序設(shè)計(jì)中幾種提高C/C++代碼效率的方法,通過對(duì)例子的分析,探討了影響程序效率的原因。關(guān)鍵詞:
    發(fā)表于 08-14 08:53 ?25次下載

    嵌入式系統(tǒng)的遠(yuǎn)程調(diào)試

      1 基本方法   圖1(a)是傳統(tǒng)的嵌入式調(diào)試方法:主機(jī)PC通過串口與從機(jī)嵌入式系統(tǒng)相連,接收從嵌入式系統(tǒng)發(fā)來的調(diào)試信息并向
    發(fā)表于 08-30 10:23 ?997次閱讀
    <b class='flag-5'>嵌入式</b>系統(tǒng)的遠(yuǎn)程<b class='flag-5'>調(diào)試</b>

    嵌入式應(yīng)用中的能耗調(diào)試技術(shù)

    嵌入式應(yīng)用中的能耗調(diào)試技術(shù)
    發(fā)表于 02-12 17:28 ?886次閱讀
    <b class='flag-5'>嵌入式</b>應(yīng)用中的能耗<b class='flag-5'>調(diào)試</b>技術(shù)

    Monitor C語言源代碼調(diào)試器設(shè)計(jì)

    為解決嵌入式系統(tǒng)不支持本地調(diào)試且開發(fā)周期較長的問題,使用了一種通過PC機(jī)去控制嵌入式系統(tǒng)的遠(yuǎn)程調(diào)試方案。該方案針對(duì)32位嵌入式設(shè)備,設(shè)計(jì)并實(shí)
    發(fā)表于 12-01 15:52 ?56次下載
    Monitor <b class='flag-5'>C</b>語言源<b class='flag-5'>代碼</b><b class='flag-5'>調(diào)試</b>器設(shè)計(jì)

    嵌入式C編程

    嵌入式C編程,非常有用的資料,介紹嵌入式C語言編程
    發(fā)表于 12-29 17:29 ?0次下載

    兩種遠(yuǎn)程調(diào)試嵌入式系統(tǒng)的介紹

    調(diào)試嵌入式系統(tǒng)與桌面操作系統(tǒng)差別很大,本文向您介紹調(diào)試嵌入式系統(tǒng)的兩種推薦方案,插樁和片上調(diào)試,
    發(fā)表于 04-14 07:43 ?2562次閱讀
    兩種遠(yuǎn)程<b class='flag-5'>調(diào)試</b><b class='flag-5'>嵌入式</b>系統(tǒng)的<b class='flag-5'>介紹</b>

    嵌入式軟件的開發(fā)流程_嵌入式軟件的調(diào)試

    本文首先介紹嵌入式軟件的發(fā)展,其次闡述了嵌入式軟件的開發(fā)流程,最后介紹嵌入式軟件的調(diào)試。
    發(fā)表于 08-31 16:02 ?6218次閱讀

    如何實(shí)現(xiàn)嵌入式系統(tǒng)遠(yuǎn)程調(diào)試

    介紹。注意,本文中的嵌入式系統(tǒng)遠(yuǎn)程調(diào)試方案僅僅代表一種方式,僅提供一種參考。如果你對(duì)嵌入式系統(tǒng)抑或是嵌入式系統(tǒng)的遠(yuǎn)程
    的頭像 發(fā)表于 11-22 11:55 ?5271次閱讀
    如何實(shí)現(xiàn)<b class='flag-5'>嵌入式</b>系統(tǒng)遠(yuǎn)程<b class='flag-5'>調(diào)試</b>

    嵌入式系統(tǒng)如何進(jìn)行遠(yuǎn)程調(diào)試

    嵌入式系統(tǒng)隨著目前科技的發(fā)展,正逐步融入人們的生活中。對(duì)于嵌入式系統(tǒng),我們應(yīng)該有所了解。就專業(yè)人員而言,他們對(duì)嵌入式系統(tǒng)早已駕輕就熟。為增進(jìn)大家對(duì)嵌入式系統(tǒng)的認(rèn)識(shí),本文將對(duì)
    發(fā)表于 12-23 10:39 ?7次下載

    嵌入式外中斷c語言代碼

    嵌入式外中斷c語言代碼(arm嵌入式開發(fā)實(shí)例)-嵌入式外中斷c語言
    發(fā)表于 07-30 11:29 ?4次下載
    <b class='flag-5'>嵌入式</b>外中斷<b class='flag-5'>c</b>語言<b class='flag-5'>代碼</b>

    嵌入式LINUX系統(tǒng)內(nèi)核和內(nèi)核模塊調(diào)試

    嵌入式LINUX系統(tǒng)內(nèi)核和內(nèi)核模塊調(diào)試(嵌入式開發(fā)和硬件開發(fā))-嵌入式LINUX系統(tǒng)內(nèi)核和內(nèi)核模塊調(diào)試? ? ? ? ? ? ? ? ?
    發(fā)表于 07-30 13:55 ?10次下載
    <b class='flag-5'>嵌入式</b>LINUX系統(tǒng)內(nèi)核和內(nèi)核模塊<b class='flag-5'>調(diào)試</b>

    嵌入式C++編程

    編程特性來構(gòu)建嵌入式系統(tǒng)您將了解如何將您的系統(tǒng)與外部外圍設(shè)備以及使用驅(qū)動(dòng)程序的有效方式集成指導(dǎo)您測(cè)試和優(yōu)化代碼以獲得更好的性能并實(shí)現(xiàn)有用的設(shè)計(jì)模式將了解如何使用 Qt,這是用于構(gòu)建嵌入式系統(tǒng)的流行 GUI 庫。內(nèi)容
    發(fā)表于 11-04 10:36 ?10次下載
    <b class='flag-5'>嵌入式</b><b class='flag-5'>C</b>++編程