简体   繁体   English

在C中,主要不需要功能吗?

[英]In C, main need not be a function?

This code compiles, but no surprises, it fails while linking (no main found): 这段代码可以编译,但不会令人惊讶,它在链接时失败(未找到主要代码):

Listing 1: 清单1:

void main();

Link error: \\mingw\\lib\\libmingw32.a(main.o):main.c:(.text+0x106) undefined reference to _WinMain@16' 链接错误:\\ mingw \\ lib \\ libmingw32.a(main.o):main.c :(。text + 0x106)对_WinMain @ 16的未定义引用

But, the code below compiles and links fine, with a warning: 但是,下面的代码可以编译和链接,但带有警告:

Listing 2: 清单2:

void (*main)();

warning: 'main' is usually a function 警告:“ main”通常是一个函数

Questions: 问题:

  1. In listing 1, linker should have complained for missing "main". 在清单1中,链接器应该抱怨缺少“ main”。 Why is it looking for _WinMain@16? 为什么要寻找_WinMain @ 16?

  2. The executable generated from listing 2 simply crashes. 从清单2生成的可执行文件完全崩溃。 What is the reason? 是什么原因?

Thanks for your time. 谢谢你的时间。

True, main doesn't need to be a function. 的确, main不必是一个函数。 This has been exploited in some obfuscated programs that contain binary program code in an array called main . 在一些混淆的程序中利用了这一点,这些程序在名为main的数组中包含二进制程序代码。

The return type of main() must be int (not void ). main()的返回类型必须为int (不是void )。 If the linker is looking for WinMain , it thinks that you have a GUI application. 如果链接程序正在寻找WinMain ,则认为您有一个GUI应用程序。

In most C compilation systems, there is no type information associated with symbols that are linked. 在大多数C编译系统中,没有与链接的符号关联的类型信息。 You could declare main as eg: 您可以将main声明为例如:

char main[10];

and the linker would be perfectly happy. 链接器将非常高兴。 As you noted, the program would probably crash, uless you cleverly initialized the contents of the array. 如您所述,程序可能会崩溃,除非您巧妙地初始化了数组的内容。

Your first example doesn't define main, it just declares it, hence the linker error. 您的第一个示例未定义main,而是对其进行了声明,因此出现了链接器错误。

The second example defines main, but incorrectly. 第二个示例定义了main,但定义不正确。

Case 1. is Windows-specific - the compiler probably generates _WinMain symbol when main is properly defined. 情况1.是特定于Windows的-正确定义main ,编译器可能会生成_WinMain符号。

Case 2. - you have a pointer, but as static variable it's initialized to zero , thus the crash. 情况2-您有一个指针,但是作为静态变量, 它被初始化为零 ,从而导致崩溃。

On Windows platforms the program's main unit is WinMain if you don't set the program up as a console app. 在Windows平台上,如果未将程序设置为控制台应用程序,则该程序的主要单元为WinMain。 The "@16" means it is expecting 16 bytes of parameters. “ @ 16”表示期望16个字节的参数。 So the linker would be quite happy with you as long as you give it a function named WinMain with 16 bytes of parameters. 因此,只要您给它一个名为WinMain的函数并带有16个字节的参数,链接器就会对您很满意。

If you wanted a console app, this is your indication that you messed something up. 如果您想要控制台应用程序,则表明您搞砸了。

You declared a pointer-to-function named main, and the linker warned you that this wouldn't work. 您声明了一个指向main的函数指针,链接器警告您这行不通。

The _WinMain message has to do with how Windows programs work. _WinMain消息与Windows程序的工作方式有关。 Below the level of the C runtime, a Windows executable has a WinMain. 在C运行时级别之下,Windows可执行文件具有WinMain。

Try redefining it as int main(int argc, char *argv[]) 尝试将其重新定义为int main(int argc, char *argv[])

What you have is a linker error. 您所拥有的是链接器错误。 The linker expects to find a function with that "signature" - not void with no parameters 链接器希望找到具有该“签名”的函数-没有参数的无效

See http://publications.gbdirect.co.uk/c_book/chapter10/arguments_to_main.html etc 参见http://publications.gbdirect.co.uk/c_book/chapter10/arguments_to_main.html

In listing 1, you are saying "There's a main() defined elsewhere in my code --- I promise!". 在清单1中,您说的是“在我的代码的其他地方定义了一个main(),我保证!”。 Which is why it compiles. 这就是为什么它会编译。 But you are lying there, which is why the link fails. 但是您躺在那里,这就是链接失败的原因。 The reason you get the missing WinMain16 error, is because the standard libraries (for Microsoft compiler) contain a definition for main(), which calls WinMain(). 之所以会丢失WinMain16错误,是因为标准库(对于Microsoft编译器)包含main()的定义,该定义调用WinMain()。 In a Win32 program, you'd define WinMain() and the linker would use the library version of main() to call WinMain(). 在Win32程序中,您将定义WinMain(),链接器将使用main()的库版本来调用WinMain()。

In Listing 2, you have a symbol called main defined, so both the compiler & the linker are happy, but the startup code will try to call the function that's at location "main", and discover that there's really not a function there, and crash. 在清单2中,您有一个称为main的符号,因此编译器和链接器都很满意,但是启动代码将尝试调用位于“ main”位置的函数,并发现那里确实没有函数,并且崩溃。

1.) An (compiler/platform) dependent function is called before code in main is executed and hence your behavior( _init in case of linux/glibc). 1.)在执行main中的代码之前,将调用一个(编译器/平台)相关的函数,因此您的行为(在linux / glibc情况下为_init )。
2) The code crash in 2nd case is justified as the system is unable to access the contents of the symbol main as a function which actually is a function pointer pointing to arbitrary location. 2)第2种情况下的代码崩溃是有道理的,因为系统无法将符号main的内容作为函数来访问,而它实际上是指向任意位置的函数指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM