C++声明"main"作为对功能的引用?

C++ declare 'main' as a reference to function?

本文关键字:功能 引用 声明 main C++      更新时间:2023-10-16

如果我将main定义为对函数的引用,该怎么办?

#include<iostream>
#include<cstring>
using namespace std;
int main1()
{
    cout << "Hello World from main1 function!" << endl;
    return 0;
}
int (&main)() = main1;

会发生什么?我在一个在线编译器中测试了错误"Segmentation fault":

此处

在VC++2013下,它将创建一个在运行时崩溃的程序!

将调用函数指针的数据作为代码的代码将被编译,该代码将在启动时立即崩溃。

我还想要一份关于这方面的ISO C++标准报价

如果你想根据如下宏定义2个入口点中的任何一个,这个概念都会很有用:

int main1();
int main2();
#ifdef _0_ENTRY
int (&main)() = main1;
#else
int (&main)() = main2;
#endif

这不是一个一致的C++程序。C++要求(第3.6.1节)

程序应包含一个称为main 的全局函数

您的程序包含一个名为main的全局非函数,它引入了与所需的main函数的名称冲突。


这样做的一个理由是,它允许托管环境在程序启动期间对main进行函数调用。它不等同于源字符串main(args),它可以是函数调用、函数指针取消引用、在函数对象上使用operator()或构造类型为main的实例。不,main必须是一个函数。

需要注意的一点是,C++标准从来没有说明main的实际类型,并阻止您观察它。因此,实现可以(而且确实可以!)重写签名,例如添加您忽略的任何int argc, char** argv, char** envp。很明显,它不知道为您的main1main2做这件事。

如果你想根据一些宏定义2个入口点中的任何一个,这将是有用的

不,不是真的。你应该这样做:

int main1();
int main2();
#ifdef _0_ENTRY
   int main() { return main1(); }
#else
   int main() { return main2(); }
#endif

由于1886年CWG问题的解决,这很快就会变得明显不成熟,目前处于"暂时准备就绪"状态,除其他外,它在[basic.start.main]中添加了以下内容:

在全局范围内声明变量main或声明具有C语言链接的名称main(在任何命名空间中)为不正规。

实践中会发生什么在很大程度上取决于实现。

在您的情况下,编译器显然将该引用实现为"伪装中的指针"。除此之外,指针还有外部链接。也就是说,您的程序导出一个名为main的外部符号,它实际上与指针占用的数据段中的内存位置相关联。链接器不需要过多地查看,而是将该内存位置记录为程序的入口点。

后来,试图使用该位置作为入口点会导致分割错误。首先,在那个位置没有任何有意义的代码。其次,仅仅试图将控制权传递给数据段内的某个位置可能会触发平台的"数据执行保护"机制。

通过这样做,您显然希望引用得到优化,即main将成为main1的另一个名称。就你而言,这并没有发生。引用作为一个独立的外部对象保留下来。

看起来您已经回答了关于发生什么的问题。

至于原因,在您的代码中,main是一个指向函数的引用/指针。这与函数不同。如果代码调用的是指针而不是函数,我预计会出现段错误。