握艹,C你main啊!

直接编译,准备仿真看看的,一段编译警告有点陌生,又特别碍眼,类似长这样的:

[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 

第一次见这种warning,很好奇,也还不清楚是否跟这个问题有关,不过我预感八九不离十了。

怎么排查或者确认这个warning就是因为项目的那个问题呢?

1. 直接仿真,查看汇编,这个___sti___12_cpp_main_cpp_mm是什么玩意

这个其实不好看懂,但能肯定的是,在仿真时,它没被调用!

2. 查网络内容或者查看编译手册

也不好找到直接的答案,但能知道这个_ctor是C++的构造函数,另外还有个叫_dtor。

综合上面的信息看,好像是在说C++的构造函数没有调用,这个构造函数又跟___sti___12_cpp_main_cpp_mm有关。

3. 直接问AI

其实也不用那么麻烦,现在什么年代了,有AI啊,直接问

虽然没有找到具体的问题点,但是可以大概找到,这个warning说,这个代码里面有C++的构造函数没调用,也提到这个C++动态初始化函数___sti___12_cpp_main_cpp_mm没调用。

下一步呢?

别急,看看这个函数名字,是不是带个main的……

大胆猜测,那是不是跟main函数有关?

也许你会去看看那个main函数,好像也没什么特别错误啊!

但是呢,不妨将想象力放开点,是不是说main函数要调用这个___sti___12_cpp_main_cpp_mm呢?

等等,你是说main函数要调用一个C++的动态初始化函数?构造函数来的?

___sti___12_cpp_main_cpp_mm这种函数也不像是直接在main函数调用的啊!

啊!不对,这个是C语言文件里的main函数,握草,应该是C艹函数!

是不是将main函数里的xxx.c改成xxx.cpp就好了呢?

好激动哦,我是不是快找到问题原因了……

直接试了下,还真是,C你main的,居然跟C艹不一样!

我压制住我心中的激动,让领导和那帮家伙再愁一会,我还没搞清楚C main和C++ main的区别,不然被领导追问,我说不出来来龙去脉,岂不是说我乱猜的,瞎猫碰到死耗子,没啥技术含量!哼!

我接着,仿真了C语言和C++的main函数。

发现C++的main多了点东西:

仿真C++ main的汇编可以看到__main是库里面的函数,其会调用这个___sti___12_cpp_main_cpp_mm函数。

这样,我可以告诉领导我找到问题原因了吗?

我还是选择等等。因为,这样无法说明怎么直接导致了项目的那个问题啊!并且,有些项目C和C++混合的工程,用C语言main函数也没问题啊,而且也没提示那个warning!

如果领导问我,我也说不出为什么,他还是会说我猜的!

为了保证,我的回答万不一失,我选择低调继续研究下。

再回头看看AI回答的那段话,它提到了构造函数和静态对象,难道是静态对象的初始化赋值问题?

于是,我尝试了好多次不同的场景,终于模拟出了这种情况。(我把完整测试源码附在文末)

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函数里面就是静态变量的初始化!

这里这个-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类的静态成员st_m。此时很容易就能理解到,这个___sti___12_cpp_main_cpp_mm函数就是执行了Msg Test::st_m = mm;的赋值。汇编中的-0x1430000就是对应MAP中.data段的_mm变量,就是Msg mm={0xaa,0x55};这个变量。通过仿真就可以证实这些内容。

所以,C++的main跟C的main不一样,C++的main更有内涵,其中还藏着一个__main,且其里面还执行了静态成员的初始化。

  • C的main,性格直爽,心里不藏任何秘密;

  • C++的main,内敛且有内涵,还悄悄地帮你做静态成员初始化。

所以,你喜欢谁的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
  • 7
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值