【问题标题】:Wrong architecture C++? Xcode 4.3错误的架构 C++? Xcode 4.3
【发布时间】:2026-01-18 07:10:01
【问题描述】:

我正在我的 Mac 上构建一个基于 Windows 的项目。我已经修复了很多错误,但是当我去编译时,它给出了以下错误:

    Undefined symbols for architecture x86_64:
  "Timer::reset()", referenced from:
      Timer::Timer() in main.o
  "Log::Log()", referenced from:
      __static_initialization_and_destruction_0(int, int)in main.o
  "Log::~Log()", referenced from:
      ___tcf_1 in main.o
  "Render::initSDL(int, int, int)", referenced from:
      init()    in main.o
  "Log::writeError(char*, ...)", referenced from:
      init()    in main.o
      _SDL_main in main.o
  "EntityManager::init(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, int)", referenced from:
      init()    in main.o
  "EntityManager::loadAssets()", referenced from:
      init()    in main.o
  "Level::getBlockCount()", referenced from:
      EntityManager::getBlockCount()       in main.o
  "Level::getBombCount()", referenced from:
      EntityManager::getBombCount()       in main.o
  "Level::getItemCount()", referenced from:
      EntityManager::getItemCount()       in main.o
  "Render::renderElement(int, int, SDL_Surface*, SDL_Rect*)", referenced from:
      renderScene()     in main.o
  "EntityManager::getElement(int, ElementType)", referenced from:
      renderScene()     in main.o
  "Render::finishRender()", referenced from:
      renderScene()     in main.o
  "EntityManager::update()", referenced from:
      _SDL_main in main.o
  "EntityManager::interpolate(double)", referenced from:
      _SDL_main in main.o
ld: symbol(s) not found for architecture x86_64
collect2: ld returned 1 exit status

我很好奇为什么它只引用了几个函数?这些函数是否包含不兼容 Mac 的内容?

例如:

int Level::getItemCount()
{
    return itemVec.size();
}

itemVec 是一个向量,只是为了清楚。

谢谢

【问题讨论】:

    标签: c++ xcode architecture


    【解决方案1】:

    如果遇到链接器错误,则表示编译器可以找到声明,但链接器找不到定义

    我想你已经知道了,但以防万一:

    对于一个方法,声明只是它的签名 例如:

    class foo 
    {
        public:
            void bar(); 
    }
    

    这是方法“void Foo::bar()”的声明,它进入一个头文件(.h,.hpp,...)

    现在这个方法的定义也包含了主体。它必须与声明相匹配。同样的例子:

    void Foo::bar()
    {
    std::cout << "Hello, world !" << std::endl;
    }
    

    这是方法“void Foo::bar()”的定义,它(通常)进入源文件(.cpp,.cxx,...)

    在您的情况下,编译器找到了声明,但链接器没有找到定义。因此,您必须找到 Timer::reset() 的定义位置,并检查该位置是否可用于链接器。

    最典型的原因是 Timer::reset() 是在 cpp 文件中定义的,并且该文件未包含在您的 xcode 项目中(别担心,如果您不这样做,这种情况一直都会发生'没有好的构建配置工具,例如 Premake、Cmake 或其他...)

    在这种情况下,符号将被声明,因为您的代码中有某个地方,#include "timer.h" 或类似的东西,但未定义,因为匹配的 cpp 未包含在您的项目中。它(可能)存在于您的硬盘上,但未在您的项目中引用。

    解决这个问题:

    1. 查找 Timer::reset 的定义位置
    2. 如果没有在任何地方定义它,那么您就是发现了问题。如果它被调用,它必须被定义
    3. 如果已定义,则检查 cpp 是否包含在您的项目中,在与 main.cpp 相同的模块中

    你提到它只发生在特定的功能上。我可能会补充一点,如果从未调用过函数,您将不会收到错误消息。您是否只有在 main.cpp 中实际调用的函数才会出现此错误消息?

    更多详情:

    据我所知(我可能是错的,因为这不是我通常遇到的情况)编译器一次处理一个文件,声明但未定义的东西是完全合法的(毕竟它可以定义在另一个文件中)在编译阶段

    链接器将所有文件放在一起,因此如果使用了符号(在您的情况下称为)并且没有定义,他肯定会抱怨。

    HTH

    【讨论】:

    • 我可能详细介绍了很多你已经知道的东西,但它可能对其他人有用,谁知道呢? :)
    【解决方案2】:

    看起来您没有与 SDL 框架或库链接(不管它是打包的)。

    在 Xcode 中,单击您的项目(文件树视图的顶部),然后单击您的 Target。然后单击摘要选项卡。这就是您要添加 SDL 框架的地方。

    (如果它是.lib,则需要在链接器中添加一个额外的标志,例如“-lsdl”)。

    与 SDL 的链接应该处理您未解决的外部问题。

    【讨论】: