这些 g++ 的“多重定义”错误是什么意思?

7

我正在进行一个项目的早期阶段(即:昨天刚开始),正在设置我的初始makefile。这非常简单。以下是文件的全部内容:

all: main.o resource.o
    g++ -o output.exe main.o resource.o

main.o: main.cpp main.h resource.h
    g++ -mwindows -o main.o main.cpp

resource.o: resource.rc
    windres resource.rc resource.o

clean:
    rm *.o 

在这一点上,我认为重要的是提到我正在使用Windows操作系统,因此我要么在Powershell中使用MinGW g++ 4.5.2,要么使用Cygwin和g++ 3.4.4进行所有操作(我尝试了两种方式,但遇到相同的错误)。
不需要打印上述所有文件的内容,简单地说,main.h包含对windows.h和resource.h的引用,main.cpp包含对main.h和几个函数的引用,其中最重要的是int WINAPI WinMain(...)函数和LRESULT CALLBACK WndProc(...)函数,resource.rc包含对一个简单菜单栏的资源定义语句,该菜单栏包含一个文件菜单和一个虚拟的第二个菜单,并引用resource.h,而resource.h仅包含用于resource.rc中所使用的ID的#define语句。
现在,我可以分别编译resource.rc和main.h并获得这两个好看的.o文件。然而,当我尝试链接它们并生成output.exe时,我会遇到以下可怕的错误列表,其中没有一个我真正理解的:
main.o:main.cpp:(.text+0x0): multiple definition of `mainCRTStartup'
c:/mingw/bin/../lib/gcc/mingw32/4.5.2/../../../crt2.o:crt1.c:(.text+0x160): first defined here
main.o:main.cpp:(.text+0x0): multiple definition of `WinMainCRTStartup'
c:/mingw/bin/../lib/gcc/mingw32/4.5.2/../../../crt2.o:crt1.c:(.text+0x140): first defined here
collect2: ld returned 1 exit status
make: *** [all] Error 1

以上内容是由Powershell生成的。Cygwin也提供了一个非常相似的错误列表,仍然集中在“多重定义”语句周围。这些多重定义似乎起源于C:/mingw/lib/crt2.o,可能还有另一个名为crt1.c的文件,因为显然C比.o文件更易读,但我无法在C:\MinGW文件夹中找到任何具有该标题的内容。
任何方向都将有所帮助,因为目前我感到相当迷失。
编辑: main.cpp中唯一的#include语句:
#include "main.h"

main.h的内容:

#ifndef _MAIN_H_
    #define _MAIN_H_

    #include <windows.h>
    #include "resource.h"

#endif

也许看一下 main.cpp 文件的开头部分会有所帮助,其中包含了头文件。我记得曾经遇到过一个类似的问题,后来解决了,原因是我明确包含的一个头文件需要由另一个头文件隐式包含,这样 #define 才能正确设置。 - hardmath
不要在“_MAIN_H_”中使用前导下划线。具有前导下划线的名称保留用于库。 - KitsuneYMG
2个回答

10

在将 .cpp 文件编译为 .o 文件时,您需要在 g++ 命令中添加 -c 参数。目前的命令会尝试从一个可执行文件创建另一个可执行文件。

正确的命令应该是:g++ -mwindows -c -o main.o main.cpp

顺便提一下,还可以添加警告标志,至少加上 -Wall


好的尝试,但是没有帮助。 - Ken Bellows
2
@KenB 你在尝试之前执行了 make clean 吗? - ssmir
我的天啊,我感觉自己像个白痴。就是这样。谢谢你们两位。 - Ken Bellows
我遇到了相同的错误。如果我正在使用CMakelist创建带有mingw的codeblock项目,请告诉我在哪里添加上述内容。 - Deepak Ingole

0

你试过调用你的主函数 int main(...) 而不是 int WINAPI WinMain(...) 吗?据我所记,MinGW 有自己的 WinMain 调用 main 函数。

[编辑]

也就是说,在你的 main.cpp 中将 int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 改为 int main(int argc, char **argv) 试试。


如何引用WinMain的参数?记住WinMain的构造方式是这样的:int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow){...} - Ken Bellows
@KenB 这些参数被用在WinMain中吗? - ssmir
是的,这是一个简单的Win32 API程序。 - Ken Bellows
以上的调整防止了 main.cpp 被编译。 - Ken Bellows

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接