【问题标题】:program execution is not started at main()程序执行未在 main() 处开始
【发布时间】:2013-11-26 13:41:57
【问题描述】:

我用 C 语言开发了很多年,现在才发现程序可以在 main() 函数之前执行代码。 这是一个代码示例

int generateNum(){
    // Some malicious code here...
    return 5;
}

static int someArray[] = {generateNum(),generateNum()}  

int main(){
     // Some code here...
}

函数generateNum()main()之前被调用了两次。

我的问题是

  1. 谁调用 generateNum()?我知道在 Windows 上是 crtexe()
  2. 此行为是否在不同平台上标准化:Windows/Linux/Android/iOS?
  3. 如何获得有关此行为的更多信息?我想在谷歌搜索,但我不知道如何描述它。
  4. 我可以在 generateNum() 中做任何我想做的事情吗?我的意思是,我可以调用 malloc() 吗? fopen() 和 fwrite() 呢?我可以打开一个套接字并通过 UDP 发送信息吗?最终我可以滥用这个函数,甚至从中调用 main() :-)

【问题讨论】:

  • 静态对象在进入 main 之前被初始化,按照标准(据我所知是 C++ 标准,但我认为 C 也是)。
  • 事实上,在进入 main 之前,可以使用虚拟静态函数从其构造函数中调用某些代码。
  • 需要注意的是,您不知道执行初始化的顺序。它甚至可以在同一台机器上的编译之间改变,具体取决于链接顺序、目标文件布局和月相。
  • “C/C++”不是一种语言。 -1 表示makes no sense 的虚构问题。

标签: c++


【解决方案1】:
  1. C++ 保证此类初始化发生在main 之前。这可以由操作系统加载器/链接器来处理,或者由链接到包含main 的目标文件的一些特殊模块来处理。对于 gcc,此处对此进行了描述:http://gcc.gnu.org/onlinedocs/gccint/Initialization.html
  2. 不完全是。 C++11, 3.6.2.4 (basic.start.init):静态存储时长的非局部变量的动态初始化是否在main的第一条语句之前完成,由实现定义。 请注意,初始化发生在您可以访问该值之前,尤其是在同一编译单元中存在对实体的任何引用概念之前。
  3. 语言标准中的[basic.start.init] 是您要查看的内容。对于具有静态存储持续时间的变量,这里的行为是动态初始化

【讨论】:

  • 我可以从初始化函数中调用 malloc() 吗? fopen() 和 fwrite() 呢?我可以打开一个套接字并通过 UDP 发送信息吗?
  • @DanielHsH,对你提到的所有事情都没有。
  • P.s.,我刚刚尝试了 malloc(),它适用于 windows 和 linux。
  • @DanielHsH,我希望它能够工作(因为您可能想要使用的许多容器类将使用动态内存分配),但我不知道——C++ 有很多规则和例外。但是:由于我们在这里讨论的是 C++ 独有的特性,所以您不想使用malloc();相反,请使用 newnew[],除非您有充分的理由不这样做(例如,与执行 free 的 C 代码接口)。
【解决方案2】:

程序应包含一个名为 main 的全局函数,这是程序的指定开始。

这并不是说在调用main 之前没有代码执行。全文引用:

3.6.1 主函数[basic.start.main]

1 程序应包含一个名为 main 的全局函数,它是 程序的指定开始。它是实现定义的 是否需要独立环境中的程序 定义一个主函数。 [注意:在独立的环境中, 启动和终止是实现定义的; 启动 包含命名空间对象的构造函数的执行 具有静态存储持续时间的范围;终止包含 为具有静态存储持续时间的对象执行析构函数。 ]

【讨论】:

    猜你喜欢
    • 2019-02-20
    • 1970-01-01
    • 2019-10-12
    • 2011-04-10
    • 1970-01-01
    • 2021-10-18
    • 2012-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多