13

此代码编译,但毫不奇怪,它在链接时失败(未找到主要代码):

清单 1:

void main();

链接错误:\mingw\lib\libmingw32.a(main.o):main.c:(.text+0x106) undefined reference to _WinMain@16'

但是,下面的代码编译和链接很好,但有一个警告:

清单 2:

void (*main)();

警告:'main' 通常是一个函数

问题:

  1. 在清单 1 中,链接器应该抱怨缺少“main”。为什么要找 _WinMain@16?

  2. 从清单 2 生成的可执行文件只是崩溃了。是什么原因?

谢谢你的时间。

4

8 回答 8

30

没错,main不需要是一个函数。这已在一些混淆程序中被利用,这些程序在一个名为main.

main() 的返回类型必须是int(not void)。如果链接器正在寻找WinMain,它认为您有一个 GUI 应用程序。

于 2010-02-12T14:27:47.640 回答
6

在大多数 C 编译系统中,没有与链接符号关联的类型信息。您可以将 main 声明为例如:

char main[10];

链接器会非常高兴。正如您所指出的,除非您巧妙地初始化了数组的内容,否则程序可能会崩溃。

您的第一个示例没有定义 main,它只是声明它,因此出现链接器错误。

第二个示例定义了 main,但不正确。

于 2010-02-12T14:30:29.333 回答
5

案例 1. 是特定于 Windows 的 - 编译器可能会在正确定义 _WinMain时生成符号。main

案例 2. - 你有一个指针,但作为静态变量,它被初始化为零,因此崩溃。

于 2010-02-12T14:30:23.913 回答
3

在 Windows 平台上,如果您不将程序设置为控制台应用程序,则程序的主要单元是 WinMain。“@16”表示它需要 16 个字节的参数。所以只要你给它一个名为 WinMain 的函数,它有 16 个字节的参数,链接器就会很高兴。

如果你想要一个控制台应用程序,这表明你搞砸了。

于 2010-02-12T15:27:18.300 回答
2

您声明了一个名为 main 的指向函数的指针,链接器警告您这不起作用。

_WinMain 消息与 Windows 程序的工作方式有关。在 C 运行时级别之下,Windows 可执行文件有一个 WinMain。

于 2010-02-12T14:31:08.270 回答
1

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

您所拥有的是链接器错误。链接器希望找到具有该“签名”的函数-没有参数的情况下不是 void

http://publications.gbdirect.co.uk/c_book/chapter10/arguments_to_main.html

于 2010-02-12T14:27:18.200 回答
0

1.)在执行 main 中的代码之前调用(编译器/平台)相关函数,因此您的行为(_init在 linux/glibc 的情况下)。
2) 第二种情况的代码崩溃是合理的,因为系统无法将符号的内容main作为函数访问,该函数实际上是指向任意位置的函数指针。

于 2010-02-12T14:49:31.300 回答
0

在清单 1 中,您说的是“我的代码中的其他地方定义了一个 main() --- 我保证!”。这就是它编译的原因。但是您躺在那里,这就是链接失败的原因。您收到缺少 WinMain16 错误的原因是因为标准库(用于 Microsoft 编译器)包含 main() 的定义,该定义调用 WinMain()。在 Win32 程序中,您将定义 WinMain(),链接器将使用 main() 的库版本来调用 WinMain()。

在清单 2 中,您定义了一个名为 main 的符号,因此编译器和链接器都很满意,但启动代码将尝试调用位于“main”位置的函数,并发现那里确实没有函数,并且碰撞。

于 2010-02-12T14:38:08.173 回答