【问题标题】:Random duplicate symbols in xcode (C++)xcode(C++)中的随机重复符号
【发布时间】:2013-09-21 06:14:01
【问题描述】:

我正在尝试在 Xcode 4.6.3 中构建一个 C++ 项目。

在我的项目中(一个非常简单的 OpenGL 游戏的开始)我有两个文件:

textures.h:

#pragma once

#include <GLUT/GLUT.h>

void load(); // load textures

GLuint dirt, water; // variables to store texture handles

textures.cpp:

#include "textures.h"

#include "util.h"

void textures::load() {
    dirt = util::loadTexture("/Some/Path/Soil.png");
    water = util::loadTexture("/Some/Path/Water_fresh.png");
}

这里 util.h 定义了 util::loadTexture 函数。

有两个文件包含 textures.h。第一个 (main.cpp) 调用 load() 函数作为初始化的一部分,并访问污垢变量以绑定 Soil.png 纹理。第二个 (Chunk.cpp) 包含 textures.h,但实际上还没有从其中访问任何内容。

当我尝试构建项目时,它给了我以下错误:

duplicate symbol _dirt in:
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/Chunk.o
duplicate symbol _water in:
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/Chunk.o
duplicate symbol _dirt in:
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/textures.o
duplicate symbol _water in:
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/main.o
    /Users/me/Library/Developer/Xcode/DerivedData/OpenGL_Testing-epporrdukapbwzawfhiwnlztzdns/Build/Intermediates/OpenGL Testing.build/Debug/OpenGL Testing.build/Objects-normal/x86_64/textures.o
ld: 4 duplicate symbols for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

我了解这意味着某处存在重复,或者标题包含多次。但是我所有的标题都使用#pragma once,并且我已经在工作区中搜索了“污垢”等,并且没有其他定义。我的其他标题工作正常,即使是多次包含的标题。我用不同的关键字多次搜索这个问题,并查看了其他类似的问题,但我发现的只是this SO question

我之前在 Xcode 中遇到过其他“随机”错误 - 例如,一个项目一直在尝试使用我已删除并用静态库替换的动态库。即使我创建了一个全新的项目,错误仍然存​​在。从终端手动编译时它可以工作。

我错过了什么?

【问题讨论】:

    标签: c++ xcode4.6 duplicate-symbol


    【解决方案1】:

    #pragma once 不会阻止头文件被多次包含。

    在编译单个文件时,它会阻止头文件被多次包含。你有(至少)三个文件,所以你要声明相同的变量 3 次。

    不要将变量定义放在头文件中。改为这样做

    // textures.h
    extern GLuint dirt, water; // variable declarations
    
    
    // textures.cpp
    GLuint dirt, water; // variable definitions
    

    您可以根据需要对变量进行尽可能多的声明(前提是它们都相同),因此可以将声明放在头文件中,您必须只有一个变量定义,因此将其放在 .cpp 中文件。

    要记住的关键是每个 .cpp 文件都是完全独立于每个其他 .cpp 文件编译的,这称为单独编译。因此,您认为 #pragma once 会阻止头文件被一个 .cpp 文件包含,只是因为它已包含在另一个 .cpp 文件中,这种想法是行不通的。你不是第一个误解这一点的人。

    【讨论】:

    • 我已经尝试用#pragma 一次代替Xcode 最初创建的#ifndef #define #endif,但它仍然不起作用......
    • 好吧,#ifndef ... 与 #pragma once 的工作方式完全相同,但由于同样的原因,它没有做你认为它应该做的事情。我发的不是小贴士,是使用全局变量的正确方法。
    • 不要停止使用 #pragma once 或 #ifndef ...它只是解决了与您认为的不同的问题。
    • 那我到底该怎么办?此外,#pragma once 对我的其他文件有效,并且快速的谷歌搜索似乎说 #pragma once 确实可以防止多重包含。虽然你可能比我知道的更多
    • @qxz 不像这样它不 你知道什么是翻译单元吗? #pragma once 和 header-fencposts 可防止在单个翻译单元中多次包含。它没有,也不能防止由多个编译的翻译单元链接到重复的定义,每个翻译单元都有自己的应该内容的“副本”成为一个全局变量。这个答案是正确的。
    猜你喜欢
    • 2018-04-03
    • 2015-06-20
    • 1970-01-01
    • 2015-02-10
    • 2016-02-03
    • 1970-01-01
    • 2013-11-12
    • 1970-01-01
    • 2014-06-28
    相关资源
    最近更新 更多