如何在Main函数之前和之后执行代码

操作系统装载程序之后,首先运行的代码并不是main的第一行,而是某些特别的代码,这些代码准备好main函数执行所需要的环境,并且负责调用main函数,这时候你才可以在main函数里放心大胆的写各种代码:申请内存、使用系统调用、触发异常、访问IO。在main函数返回之后,他会记录main函数的返回值,调用atexit注册的函数,然后结束进程。
——《程序员的自我修养--链接、装载与库》

  • main前:
    程序在执行时会调用各种各样的运行时库函数,因此执行前main函数前必须要初始化好运行时库,mainCRTStartup函数会负责相应的初始化工作,他会完成一些C全局变量以及C内存分配等初始化工作,在C++里,还要执行全局类对象的构造函数。最后,mainCRTStartup才调用main函数。

  • main后:
    在main函数返回之后,他会记录main函数的返回值,调用atexit注册的函数,然后结束进程。

  • 示例代码:

#include 
#include 

class Tmp {
public:
    Tmp() {
        qDebug() << Q_FUNC_INFO;
    }
    ~Tmp() {
        qDebug() << Q_FUNC_INFO;
    }
};

int main_before() {
    qDebug() << Q_FUNC_INFO;
    return 0;
}

void main_after() {
    qDebug() << Q_FUNC_INFO;
}

int doExit(void (*func)(void)) {
    return atexit(func);
}

int nBefore = main_before();
int nAfter = doExit(main_after);
Tmp oTmp;

int main(int argc, char *argv[])
{
    qDebug() << Q_FUNC_INFO;
//    QCoreApplication app(argc, argv);
//    return app.exec(); // 进入qt的事件循环
    return 0;
}


  • 运行结果
int main_before()
Tmp::Tmp()
int main(int, char**)
Tmp::~Tmp()
void main_after()
  • 思考
    感兴趣的同学可以把main函数里面注释掉的那两行代码放开,观察一下运行结果,然后思考一下全局对象的释放时机。

  • 封装

#ifdef __cplusplus
extern "C" {
#endif

__inline int boot_run_atstartup(void (*func)(void)) { func(); return 0;}
__inline int boot_run_atexit(void (*func)(void)) { return atexit(func);}

#ifdef __cplusplus
}
#endif

#define BOOT_RUN_STARTUP(func) VARIABLE_IS_NOT_USED static int __anonymous_run_variable_startup_##func = boot_run_atstartup(func)
#define BOOT_RUN_EXIT(func) VARIABLE_IS_NOT_USED static int __anonymous_run_variable_exit_##func = boot_run_atexit(func)

你可能感兴趣的:(如何在Main函数之前和之后执行代码)