在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

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

C++的全鏈路追蹤方案

汽車(chē)電子技術(shù) ? 來(lái)源:程序喵大人 ? 作者:程序喵大人 ? 2023-02-21 14:15 ? 次閱讀

**背景:**本人主要在做C++ SDK的開(kāi)發(fā),需要給到業(yè)務(wù)端去集成,在集成的過(guò)程中可能會(huì)出現(xiàn)某些功能性bug,即沒(méi)有得到想要的結(jié)果。那怎么調(diào)試?

**分析:**這種問(wèn)題其實(shí)調(diào)試起來(lái)稍微有點(diǎn)困難,它不像crash,當(dāng)發(fā)生crash時(shí)還能拿到堆棧信息去分析,然而功能性bug沒(méi)有crash,也就沒(méi)法捕捉對(duì)應(yīng)到當(dāng)時(shí)的堆棧信息。因?yàn)椴皇窃诒镜兀矝](méi)法用編譯器debug。那思路就剩log了,一種方式是考慮在SDK內(nèi)部的關(guān)鍵路徑下打印詳細(xì)的log,當(dāng)出現(xiàn)問(wèn)題時(shí)拿到log去分析。然而總有漏的時(shí)候,誰(shuí)能保證log一定打的很全面,很有可能問(wèn)題就出現(xiàn)在沒(méi)有l(wèi)og的函數(shù)中。

**解決:**基于上面的背景和問(wèn)題分析,考慮是否能做一個(gè)全鏈路追蹤的方案,把打印出整個(gè)SDK的調(diào)用路徑,從哪個(gè)函數(shù)進(jìn)入,從哪個(gè)函數(shù)退出等。

**想法1:**可以考慮在SDK的每個(gè)接口都加一個(gè)context結(jié)構(gòu)體參數(shù),記錄下來(lái)函數(shù)的調(diào)用路徑,這可能是比較通用有效的方案,但是SDK接口已經(jīng)固定了,更改接口要面臨的困難很大,業(yè)務(wù)端基本不會(huì)同意,所以這種方案不適合我們現(xiàn)有情況,當(dāng)然一個(gè)從0開(kāi)始建設(shè)的中間件和SDK可以考慮考慮。

**想法2:**有沒(méi)有一種不用改接口,還能追蹤到函數(shù)調(diào)用路徑的方案?

繼續(xù)沿著這個(gè)思路繼續(xù)調(diào)研,我找到了gcc和clang編譯器的一個(gè)編譯參數(shù):-finstrument-functions,編譯時(shí)添加此參數(shù)會(huì)在函數(shù)的入口和出口處觸發(fā)一個(gè)固定的回調(diào)函數(shù),即:

__cyg_profile_func_enter(void *callee, void *caller);
__cyg_profile_func_exit(void *callee, void *caller);

參數(shù)就是callee和caller的地址,那怎么將地址解析成對(duì)應(yīng)函數(shù)名?可以使用dladdr函數(shù):

int dladdr(const void *addr, Dl_info *info);

看下下面的代碼:

// tracing.cc


#include 
#include   // for dladdr
#include 
#include 
#include 


#ifndef NO_INSTRUMENT
#define NO_INSTRUMENT __attribute__((no_instrument_function))
#endif


extern "C" __attribute__((no_instrument_function)) void __cyg_profile_func_enter(void *callee, void *caller) {
    Dl_info info;
    if (dladdr(callee, &info)) {
        int status;
        const char *name;
        char *demangled = abi::__cxa_demangle(info.dli_sname, NULL, 0, &status);
        if (status == 0) {
            name = demangled ? demangled : "[not demangled]";
        } else {
            name = info.dli_sname ? info.dli_sname : "[no dli_sname nd std]";
        }


        printf("enter %s (%s)\\n", name, info.dli_fname);


        if (demangled) {
            free(demangled);
            demangled = NULL;
        }
    }
}


extern "C" __attribute__((no_instrument_function)) void __cyg_profile_func_exit(void *callee, void *caller) {
    Dl_info info;
    if (dladdr(callee, &info)) {
        int status;
        const char *name;
        char *demangled = abi::__cxa_demangle(info.dli_sname, NULL, 0, &status);
        if (status == 0) {
            name = demangled ? demangled : "[not demangled]";
        } else {
            name = info.dli_sname ? info.dli_sname : "[no dli_sname and std]";
        }
        printf("exit %s (%s)\\n", name, info.dli_fname);


        if (demangled) {
            free((void *)demangled);
            demangled = NULL;
        }
    }
}

這是測(cè)試文件:

// test_trace.cc
void func1() {}


void func() { func1(); }


int main() { func(); }
將test_trace.cc和tracing.cc文件同時(shí)編譯鏈接,即可達(dá)到鏈路追蹤的目的:
g++ test_trace.cc tracing.cc -std=c++14 -finstrument-functions -rdynamic -ldl;./a.out
輸出:enter main (./a.out)
enter func() (./a.out)
enter func1() (./a.out)
exit func1() (./a.out)
exit func() (./a.out)
exit main (./a.out)

如果在func()中調(diào)用了一些其他的函數(shù)呢?

#include 
#include 


void func1() {}


void func() {
    std::vector<int> v{1, 2, 3};
    std::cout << v.size();
    func1();
}


int main() { func(); }

再重新編譯后輸出會(huì)是這樣:

enter [no dli_sname nd std] (./a.out)
enter [no dli_sname nd std] (./a.out)
exit [no dli_sname and std] (./a.out)
exit [no dli_sname and std] (./a.out)
enter main (./a.out)
enter func() (./a.out)
enter std::allocator<int>::allocator() (./a.out)
enter __gnu_cxx::new_allocator<int>::new_allocator() (./a.out)
exit __gnu_cxx::new_allocator<int>::new_allocator() (./a.out)
exit std::allocator<int>::allocator() (./a.out)
enter std::vector<int, std::allocator<int> >::vector(std::initializer_list<int>, std::allocator<int> const&) (./a.out)
enter std::_Vector_base<int, std::allocator<int> >::_Vector_base(std::allocator<int> const&) (./a.out)
enter std::_Vector_base<int, std::allocator<int> >::_Vector_impl::_Vector_impl(std::allocator<int> const&) (./a.out)
enter std::allocator<int>::allocator(std::allocator<int> const&) (./a.out)
enter __gnu_cxx::new_allocator<int>::new_allocator(__gnu_cxx::new_allocator<int> const&) (./a.out)
exit __gnu_cxx::new_allocator<int>::new_allocator(__gnu_cxx::new_allocator<int> const&) (./a.out)
exit std::allocator<int>::allocator(std::allocator<int> const&) (./a.out)
exit std::_Vector_base<int, std::allocator<int> >::_Vector_impl::_Vector_impl(std::allocator<int> const&) (./a.out)
exit std::_Vector_base<int, std::allocator<int> >::_Vector_base(std::allocator<int> const&) (./a.out)

上面我只貼出了部分信息,這顯然不是我們想要的,我們只想要顯示自定義的函數(shù)調(diào)用路徑,其他的都想要過(guò)濾掉,怎么辦?

這里可以將自定義的函數(shù)都加一個(gè)統(tǒng)一的前綴,在打印時(shí)只打印含有前綴的符號(hào),這種個(gè)人認(rèn)為是比較通用的方案。

下面是我過(guò)濾掉std和gnu子串的代碼:

if (!strcasestr(name, "std") && !strcasestr(name, "gnu")) {
    printf("enter %s (%s)\\n", name, info.dli_fname);
}


if (!strcasestr(name, "std") && !strcasestr(name, "gnu")) {
    printf("exit %s (%s)\\n", name, info.dli_fname);
}

重新編譯后就會(huì)輸出我想要的結(jié)果:

g++ test_trace.cc tracing.cc -std=c++14 -finstrument-functions -rdynamic -ldl;./a.out
輸出:enter main (./a.out)
enter func() (./a.out)
enter func1() (./a.out)
exit func1() (./a.out)
exit func() (./a.out)
exit main (./a.out)

還有一種方式是在編譯時(shí)使用下面的參數(shù):

-finstrument-functions-exclude-file-list

它可以排除不想要做trace的文件,但是這個(gè)參數(shù)只在gcc中可用,在clang中卻不支持 ,所以上面的字符串過(guò)濾方式更通用一些。

上面只能拿到函數(shù)的名字,不能定位到具體的文件和行號(hào),如果想要獲得更多信息,需要結(jié)合bfd系列參數(shù)(bfd_find_nearest_line)和libunwind一起使用,大家可以繼續(xù)研究。。。

tips1: 這是一篇拋磚引玉的文章,本人不是后端開(kāi)發(fā),據(jù)我所知后端C++中有很多成熟的trace方案,大家有更好的方案可以留言,分享一波。

tips2: 上面的方案可以達(dá)到鏈路追蹤的目的,但本人最后沒(méi)有應(yīng)用到項(xiàng)目中,因?yàn)楸救嗽谧龅捻?xiàng)目對(duì)性能要求較高,使用此種方案會(huì)使整個(gè)SDK性能下降嚴(yán)重,無(wú)法滿(mǎn)足需求正常運(yùn)行。于是暫時(shí)放棄了鏈路追蹤的這個(gè)想法。

本文的知識(shí)點(diǎn)還是值得了解一下的,大家或許會(huì)用得到。在研究的過(guò)程中我也發(fā)現(xiàn)了一個(gè)基于此種方案的開(kāi)源項(xiàng)目(call-stack-logger),感興趣的也可以去了解了解。

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

    關(guān)注

    0

    文章

    183

    瀏覽量

    20043
  • 編譯器
    +關(guān)注

    關(guān)注

    1

    文章

    1656

    瀏覽量

    49898
  • BUG
    BUG
    +關(guān)注

    關(guān)注

    0

    文章

    156

    瀏覽量

    15961
收藏 人收藏

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    實(shí)時(shí)監(jiān)測(cè)倒換系統(tǒng)

    系統(tǒng)移動(dòng)通信解決方案旨在對(duì)移動(dòng)運(yùn)營(yíng)商光纜重要或應(yīng)用場(chǎng)合進(jìn)行實(shí)時(shí)監(jiān)控和故障恢復(fù)快速的保護(hù)倒換,保證光網(wǎng)絡(luò)鏈路層的穩(wěn)定,提高光網(wǎng)絡(luò)的可靠性;同時(shí)該系統(tǒng)可輔助網(wǎng)管中心實(shí)時(shí)監(jiān)視全網(wǎng)光功率動(dòng)態(tài)、為值勤維護(hù)人員快速
    發(fā)表于 12-02 09:50

    壓測(cè)一招搞定,阿里云性能測(cè)試鉑金版發(fā)布

    版本的發(fā)布,就是把全局的復(fù)雜流量形態(tài)編排、串聯(lián)這塊的工作變成一個(gè)基于直白式交互的功能,可以讓用戶(hù)在壓測(cè)場(chǎng)景構(gòu)造和復(fù)現(xiàn)上無(wú)需編碼,網(wǎng)頁(yè)上就能編排復(fù)雜的壓測(cè)業(yè)務(wù),希望以更智能而簡(jiǎn)單的方案
    發(fā)表于 01-30 14:13

    基于分布式調(diào)用監(jiān)控技術(shù)的全息排查功能

    的分布式追蹤功能結(jié)合周邊的本地堆棧排查,性能Metrics統(tǒng)計(jì),業(yè)務(wù)全息排查三大附加功能,形成了完整的
    發(fā)表于 08-07 17:02

    監(jiān)控工具Skywalking使用指南

    國(guó)產(chǎn)監(jiān)控工具Skywalking
    發(fā)表于 09-03 14:26

    C++設(shè)計(jì)校園最短路徑的設(shè)計(jì)方案

    C++設(shè)計(jì)校園最短路徑的設(shè)計(jì)方案
    發(fā)表于 12-30 15:04 ?1次下載

    淺談OPPO設(shè)計(jì)的首個(gè)Android色彩管理系統(tǒng)

    2020年11月18日,中國(guó),深圳--今日,OPPO在以“躍遷·致善”為主題的未來(lái)科技大會(huì)2020(OPPO INNO DAY 2020)上,正式推出OPPO色彩管理系統(tǒng),同時(shí)也是面向未來(lái)廣色域、高色深時(shí)代設(shè)計(jì)的首個(gè)And
    的頭像 發(fā)表于 11-18 16:25 ?2067次閱讀

    2021 OPPO開(kāi)發(fā)者大會(huì):運(yùn)營(yíng)

    2021 OPPO開(kāi)發(fā)者大會(huì):運(yùn)營(yíng) 2021 OPPO開(kāi)發(fā)者大會(huì)上介紹了運(yùn)營(yíng),技術(shù)能
    的頭像 發(fā)表于 10-27 15:07 ?2420次閱讀
    2021 OPPO開(kāi)發(fā)者大會(huì):<b class='flag-5'>全</b><b class='flag-5'>鏈</b><b class='flag-5'>路</b>運(yùn)營(yíng)

    安歌科技Enotek如何實(shí)現(xiàn)智能物流解決方案

    除了核心軟硬件自研自產(chǎn)外,作為一家深耕物流領(lǐng)域十四余載的工業(yè)智能物流解決方案提供商,安歌科技始終秉承“以創(chuàng)新,致未來(lái)”的初心,致力于為各行業(yè)提供安全可靠、智能高效的整體集成
    的頭像 發(fā)表于 11-11 15:14 ?988次閱讀

    追蹤系統(tǒng)SkyWalking的原理

    什么是追蹤追蹤的原理
    的頭像 發(fā)表于 01-17 11:00 ?4583次閱讀

    介紹Node.js應(yīng)用信息獲取的方法

    這種技術(shù),就是Node.js應(yīng)用追蹤。它是 Node.js 在涉及到復(fù)雜服務(wù)端業(yè)務(wù)場(chǎng)景中,必不可少的技術(shù)保障。
    的頭像 發(fā)表于 02-10 11:21 ?824次閱讀

    淺談C語(yǔ)言與C++的前世今生

    C++開(kāi)發(fā)人員將有這些問(wèn)題歸咎于C,而C開(kāi)發(fā)人員則認(rèn)為C++過(guò)于瘋狂。我覺(jué)得站在C的角度看C++
    發(fā)表于 05-26 09:27 ?629次閱讀
    淺談<b class='flag-5'>C</b>語(yǔ)言與<b class='flag-5'>C++</b>的前世今生

    C++之父新作帶你勾勒現(xiàn)代C++地圖

    為了幫助大家解決這些痛點(diǎn)問(wèn)題,讓大家領(lǐng)略現(xiàn)代C++之美,掌握其中的精髓,更好地使用C++C++之父Bjarne Stroustrup坐不住了,他親自操刀寫(xiě)就了這本《C++之旅》!
    的頭像 發(fā)表于 10-30 16:35 ?1247次閱讀
    <b class='flag-5'>C++</b>之父新作帶你勾勒現(xiàn)代<b class='flag-5'>C++</b>地圖

    C++簡(jiǎn)史:C++是如何開(kāi)始的

    MISRA C++:2023,MISRA? C++ 標(biāo)準(zhǔn)的下一個(gè)版本,來(lái)了!為了幫助您做好準(zhǔn)備,我們介紹了 Perforce 首席技術(shù)支持工程師 Frank van den Beuken 博士撰寫(xiě)
    的頭像 發(fā)表于 01-11 09:00 ?923次閱讀
    <b class='flag-5'>C++</b>簡(jiǎn)史:<b class='flag-5'>C++</b>是如何開(kāi)始的

    智能推送系統(tǒng)的統(tǒng)計(jì)功能:數(shù)據(jù)閉環(huán)下的運(yùn)營(yíng)增效革命

    在精細(xì)化運(yùn)營(yíng)時(shí)代,APP企業(yè)面臨的核心挑戰(zhàn)已從“如何觸達(dá)用戶(hù)”轉(zhuǎn)向“如何量化每一次觸達(dá)的價(jià)值”。MobPush智能推送系統(tǒng)的統(tǒng)計(jì)功能,通過(guò)追蹤用戶(hù)從推送接收、點(diǎn)擊到最終轉(zhuǎn)化的完整
    的頭像 發(fā)表于 02-25 17:23 ?309次閱讀

    泰克科技測(cè)試解決方案助力人形機(jī)器人發(fā)展

    在剛剛舉辦的人形機(jī)器人科技創(chuàng)新大會(huì)中,泰克科技(Tektronix)作為測(cè)試、測(cè)量和監(jiān)測(cè)解決方案的創(chuàng)新者,展示了其測(cè)試解決方案,為與會(huì)
    的頭像 發(fā)表于 05-21 14:56 ?407次閱讀
    主站蜘蛛池模板: 五月天天 | heyzo在线播放4k岛国 | 毛片网此 | 天天艹天天艹 | 香港澳门a级三级三级全黄 香港经典a毛片免费观看爽爽影院 | 久久久久久久蜜桃 | 国产女人在线视频 | 日本色免费 | 亚洲一区二区在线视频 | 欧美性xxxxbbbb| 天堂资源在线最新版 | 全国最大色成免费网站 | 亚洲综合色婷婷在线观看 | 色综合天 | 日韩一级在线播放免费观看 | 69japanese日本100| 四虎永久在线日韩精品观看 | 精品国产免费久久久久久婷婷 | 日本黄色高清视频网站 | 精品国产中文一级毛片在线看 | 2345成人高清毛片 | 国产一区二区三区波多野吉衣 | 欧美综合视频 | 人人澡人人搞 | 国产乱人视频在线看 | www.久久精品视频 | 免费看啪啪的网站 | 日日噜噜噜夜夜爽爽狠狠图片 | 午夜影院a | 猛操网| 久久国产午夜精品理论片34页 | 天堂最新版免费观看 | 天天操天天舔天天射 | 精品影视网站入口 | 午夜操操| 最新欧美精品一区二区三区 | 天天操天天干天天 | 色人岛 | 91国内在线国内在线播放 | 国产成人三级经典中文 | 亚洲国产成人成上人色 |