【问题标题】:C++: duplicate symbol using Makefile and object declarationC++:使用 Makefile 和对象声明的重复符号
【发布时间】:2021-04-02 16:39:53
【问题描述】:


我在
a.h

中定义了一个结构
#IFNDEF
#define A_H
struct a_struct
{
int val;
int val_b;
}a;
#endif

ma​​in.cppa.cpp 都包含标题

#include "a.h"

当我使用 makefile 时:

a.o: a.cpp a.h
    g++ -std=c++11 -c $<
main.o: main.cpp a.h
    g++ -std=c++11 -c $<
main: main.o a.o
    g++ -std=c++ $^ -o $@

发生编译错误:

duplicate symbol '_a' in:
    a.o
    main.o

a 是否在 a.cppma​​in.cpp 中重新定义? 有没有办法在不改变 a.h 的情况下解决这个问题?
如果不可能,我该如何更改代码? 提前谢谢你:)

【问题讨论】:

  • Is a being redefined in a.cpp and main.cpp? 是的。 Is there a way to resolve this issue without changing a.h?没有
  • 你为什么不想改变a.h?你能复制一份,叫它b.h,然后修复它吗?
  • @Beta @tkausl 我想尽量减少对a.h 的更改,因为它不属于我。如果我能够获得a.h,我该如何解决这个问题?

标签: c++ struct makefile g++


【解决方案1】:

问题在于a.h 都声明了数据类型struct a_struct 并且a 声明为该类型的变量。每个包含该标题的翻译单元——例如,基于a.cpp 的翻译单元和基于main.cpp 的翻译单元将因此声明自己的a,如果两个这样的翻译单元对同一个程序有贡献,则未定义的行为结果。由于重复符号而被拒绝的程序是由这种情况引起的 UB 的一种可能(并且相当普遍)表现。

所以,

a.cpp 和 main.cpp 中是否重新定义了 a?

是的。包含在每个源文件的翻译单元中的a 的声明直接导致在每个源文件中定义a。从技术上讲,这些声明本身并不是定义,但这有点令人毛骨悚然。

有没有办法在不改变 a.h 的情况下解决这个问题?

如果程序被修改为只有一个翻译单元#includes a.h,无论是直接还是间接,那么它就不会有a 的多个定义(来自它现在拥有它们的源)。目前尚不清楚这是否对您来说是一个可行的解决方案,但这似乎值得怀疑。

如果不可能,我该如何更改代码?

最简单的更改是从a.h 中删除a 的声明:

#ifndef A_H
#define A_H
struct a_struct
{
int val;
int val_b;
};  // <-- the main change is here
#endif

如果您确实需要struct a_struct 类型的外部变量a,那么您应该在标题中添加extern 来声明它

extern struct a_struct a;

到标题

在其中一个 .cpp 文件中添加 a 的非(显式)extern 声明:

struct a_struct a;

从文件名看来,a.cpp 文件似乎是后者的正确位置,但如果您不想修改它,则可以改用 main.cpp

【讨论】:

    猜你喜欢
    • 2018-06-17
    • 1970-01-01
    • 2020-01-28
    • 1970-01-01
    • 2013-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多