【问题标题】:What's with these g++ "multiple definition" errors?这些 g++“多重定义”错误是怎么回事?
【发布时间】:2011-06-14 03:36:29
【问题描述】:

我正处于一个项目的早期阶段(阅读:昨天刚开始),我正在设置我的初始 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 才能正确设置。
  • 不要在_MAIN_H_ 中使用前导下划线。带有前导下划线的名称是为库保留的。

标签: c++ winapi makefile g++ mingw


【解决方案1】:

您是否尝试调用您的主要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){...}
  • @KenB WinMain 中是否使用了这个参数?
  • 是的。这是一个简单的 Win32 API 程序。
  • 以上调整使main.cpp无法被编译。
【解决方案2】:

当您将 .cpp 文件编译为 .o 文件时,您缺少 g++ 的 -c 参数。就像现在一样,您正在尝试从另一个可执行文件创建一个可执行文件。

g++ -mwindows -o main.o main.cpp 应该是g++ -mwindows -c -o main.o main.cpp

同时添加警告标志,至少-Wall

【讨论】:

  • 好电话,但没有帮助。
  • @KenB 你在尝试之前make clean 吗?
  • 我的话。我觉得自己像个白痴。做到了。谢谢你们俩。
  • 我遇到了同样的错误。如果我使用 CMakelist 和 mingw 创建代码块项目,请告诉我在哪里添加上述内容。
猜你喜欢
  • 1970-01-01
  • 2022-01-23
  • 1970-01-01
  • 2021-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-06
相关资源
最近更新 更多