1. 握艸,C你main啊!

        共 5665字,需瀏覽 12分鐘

         ·

        2024-06-25 08:23

        我看了這代碼這問題,直呼“握草”,main的!
        事情是這樣的,前段時間來了個新項目,大家都太忙了,沒人積極搞啊。于是,領導啟用了他前不久招的“得意門生”,把這活兒交給他了。
        這項目其實也沒很多活要干,最主要的是要從一個C++項目代碼移植到平臺的基礎工程里,當然這個基礎工程是C語言的。
        這小伙,一頓操作猛如虎,風風火火搞了幾周,基本功能終于跑起來了!
        領導心想:哎呀果然沒看錯人。接著沒幾天領導就向上面領導吹捧一番,說這項目怎樣怎樣難,這誰誰又怎么怎么排除萬難的,最終搞出來了。反正,領導開心,小伙的績效也差不了哪去了!
        直到最近,出了一個bug,離奇古怪,某功能在你意想不到的情況下出錯。領導又派出了他的“得意門生”,噼里啪啦的,搞了一個多星期了,啥頭緒也沒有……
        這問題可被甲方發(fā)現(xiàn)了的,而且臨近交付樣品了,這把領導急的不要不要的。
        領導憋出了個大招,“三個臭皮匠頂個諸葛亮”,發(fā)動整個小組找bug……
        尼瑪,我也被牽連了,翻了半天也沒頭緒,這代碼一坨坨的具體是啥含義,我也懶得去研究。
        干脆直接編譯,準備仿真看看的,一段編譯警告有點陌生,又特別礙眼,類似長這樣的:
        [elxr] (warning #222) The program contains no reference to _ctors.The following C++ dynamic initialization routines will probably not get called: ___sti___12_cpp_main_cpp_mm    from cpp_main.omain() (from c_main.o) was probably not compiled as C++.
        呵呵,這只是個warning,估計那小伙也不care!
        我第一次見這種warning,很好奇,也還不清楚是否跟這個問題有關,不過我預感八九不離十了。
        怎么排查或者確認這個warning就是因為項目的那個問題呢?
        1. 直接仿真,查看匯編,這個___sti___12_cpp_main_cpp_mm是什么玩意

        這個其實不好看懂,但能肯定的是,在仿真時,它沒被調用!
        2. 查網絡內容或者查看編譯手冊
        也不好找到直接的答案,但能知道這個_ctor是C++的構造函數(shù),另外還有個叫_dtor。
        綜合上面的信息看,好像是在說C++的構造函數(shù)沒有調用,這個構造函數(shù)又跟___sti___12_cpp_main_cpp_mm有關。
        3. 直接問AI
        其實也不用那么麻煩,現(xiàn)在什么年代了,有AI啊,直接問
        雖然沒有找到具體的問題點,但是可以大概找到,這個warning說,這個代碼里面有C++的構造函數(shù)沒調用,也提到這個C++動態(tài)初始化函數(shù)___sti___12_cpp_main_cpp_mm沒調用。
        下一步呢?
        別急,看看這個函數(shù)名字,是不是帶個main的……
        大膽猜測,那是不是跟main函數(shù)有關?
        也許你會去看看那個main函數(shù),好像也沒什么特別錯誤??!
        但是呢,不妨將想象力放開點,是不是說main函數(shù)要調用這個___sti___12_cpp_main_cpp_mm呢?
        等等,你是說main函數(shù)要調用一個C++的動態(tài)初始化函數(shù)?構造函數(shù)來的?
        ___sti___12_cpp_main_cpp_mm這種函數(shù)也不像是直接在main函數(shù)調用的啊!
        ??!不對,這個是C語言文件里的main函數(shù),握草,應該是C艸函數(shù)!
        是不是將main函數(shù)里的xxx.c改成xxx.cpp就好了呢?
        好激動哦,我是不是快找到問題原因了……
        直接試了下,還真是,C你main的,居然跟C艸不一樣!
        我壓制住我心中的激動,讓領導和那幫家伙再愁一會,我還沒搞清楚C main和C++ main的區(qū)別,不然被領導追問,我說不出來來龍去脈,豈不是說我亂猜的,瞎貓碰到死耗子,沒啥技術含量!哼!
        我接著,仿真了C語言和C++的main函數(shù)。
        發(fā)現(xiàn)C++的main多了點東西:


        仿真C++ main的匯編可以看到__main是庫里面的函數(shù),其會調用這個___sti___12_cpp_main_cpp_mm函數(shù)。
        這樣,我可以告訴領導我找到問題原因了嗎?
        我還是選擇等等。因為,這樣無法說明怎么直接導致了項目的那個問題啊!并且,有些項目C和C++混合的工程,用C語言main函數(shù)也沒問題啊,而且也沒提示那個warning!
        如果領導問我,我也說不出為什么,他還是會說我猜的!
        為了保證,我的回答萬不一失,我選擇低調繼續(xù)研究下。
        再回頭看看AI回答的那段話,它提到了構造函數(shù)和靜態(tài)對象,難道是靜態(tài)對象的初始化賦值問題?
        于是,我嘗試了好多次不同的場景,終于模擬出了這種情況。(我把完整測試源碼附在文末)
        typedef struct{  unsigned int  id;  unsigned char   len;} Msg;class Test {    public:        Test() {      }        int n;        static int st_n;        static Msg st_m;};Msg mm={0xaa,0x55};Msg Test::st_m = mm;int Test::st_n = 0x123;
        其實,這個___sti___12_cpp_main_cpp_mm函數(shù)里面就是靜態(tài)變量的初始化!
        這里這個-0x142FF94值,即0xFEBD006C,實際是對應MAP文件中的.bss段中的_st_m__4Test變量。
         .data            febd0000+000008 _mm .text            00000b9e+000002 _multiBreak .text            00000b9a+000000 _multiCall .text            00001b2c+00004a _open .text            000018b6+000084 _raise .text            00001b06+000026 _read .text            00001856+000060 _signal .bss             febd006c+000008 _st_m__4Test .data            febd0008+000004 _st_n__4Test
        那么,這個_st_m__4Test變量是什么呢?就是上面代碼Test類的靜態(tài)成員st_m。此時很容易就能理解到,這個___sti___12_cpp_main_cpp_mm函數(shù)就是執(zhí)行了Msg Test::st_m = mm;的賦值。匯編中的-0x1430000就是對應MAP中.data段的_mm變量,就是Msg mm={0xaa,0x55};這個變量。通過仿真就可以證實這些內容。
        所以,C++的main跟C的main不一樣,C++的main更有內涵,其中還藏著一個__main,且其里面還執(zhí)行了靜態(tài)成員的初始化。
        • C的main,性格直爽,心里不藏任何秘密;
        • C++的main,內斂且有內涵,還悄悄地幫你做靜態(tài)成員初始化。
        所以,你喜歡誰的main?
        好了,話題扯遠了,這下我應該可以向領導匯報了吧。
        于是,我打算好好科普C和C++的main main的時候,領導卻說,那誰誰已經再同步C++項目的啟動部分文件就OK了,而且已經檢討移植項目文件不徹底問題了,問題已經解決了。于是,讓我去忙別的去了。
        我……欲言又止……
        main的,艸!

        測試源碼
        // c_main.cextern int test_func(void);#ifndef CPP_MAINint main(void){    test_func();    return 0;}#endif


        // cpp_main.cpptypedef struct{ unsigned int id; unsigned char len;} Msg;class Test { public: Test() { } int n; static int st_n; static Msg st_m;};Msg mm={0xaa,0x55};Msg Test::st_m = mm;int Test::st_n = 0x123;Test gt; extern "C" { int test_func(void){ Test t; int x; t.n = 12; if(t.st_n == 0x123) { x = 100; } if(t.st_m.id == 0xaa) { x = 200; } if(gt.st_m.id == 0xaa) { x = 2200; } return x; }}#ifdef CPP_MAINint main(){ test_func(); return 0;}#endif

        我知道你看完本文就退出的了,就算收藏也是吃灰的,不如你點個轉發(fā)、點贊在看再走,我是會很感激你的哦!

        瀏覽 404
        4點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        4點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
          
          

            1. 亚州少妇| 一级免费特黄视频 | 国产一级片免费观看 | 欧美边摸边添边做边爱叫床视频 | 夜夜无码|