我已经为嵌入式系统编写了一些 C++ 代码,效果非常好。当前的任务是在 PC 上模拟此设备的行为。一些代码必须移植:对于第一次测试,我使用 mingw (g++),而嵌入式系统是 STM32 并使用 KEIL µVision 工具链。
我遇到了一个与功能行为无关的问题,而不是编译器特定的怪异问题。我在匿名命名空间中定义了 2 个类,因为它们包含在整个项目中。现在在嵌入式设备上编译和运行没有问题。 g++ 提示 undefined reference !
当我删除类周围的匿名命名空间时,它会编译并运行!但为什么?下面是一些重现这种情况的示例代码: main.cpp :
#include "notmain.h"
#include "theclass.h"
A *ourA=NULL;
int main()
{
theA = new A();
theA->dostuff(1024);
sunshine sun;
sun.Init();
}
notmain.cpp:
#include "notmain.h"
#include "theclass.h"
void sunshine::Init()
{
theA->dostuff(127);
}
notmain.h:
#ifndef NOTMAIN_H_
#define NOTMAIN_H_
class sunshine
{
public:
void Init();
};
#endif
类.h:
#ifndef THECLASS_H_
#define THECLASS_H_
#include <stdio.h>
#define theA ourA
namespace
{
class A
{
public:
void dostuff(int b)
{
a = b;
printf("Hello: %d\n",a);
}
private:
int a;
};
}
extern A *ourA;
#endif
编译器/链接器输出:
09:09:57 ** 项目 Testo 的配置调试增量构建 **
信息:Internal Builder 用于构建
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o main.o "..\main.cpp"
g++ -O0 -g3 -Wall -c -fmessage-length=0 -o notmain.o "..\notmain.cpp"
g++ -o Testo.exe notmain.o main.o
notmain.o:在函数 ZN8sunshine4InitEv' 中:
D:\Projekte\Testo\Debug/../notmain.cpp:6: undefined reference
ourA'
collect2.exe:错误:ld 返回了 1 个退出状态
09:09:57 Build Finished (took 702ms)
删除该 namespace 可以解决问题,但为什么它在 KEIL 中编译、链接和工作?谁能给我解释一下?
最佳答案
我认为这是对匿名命名空间功能的滥用。它与您要实现的目标完全相反。
匿名命名空间用于将定义本地化到单个翻译单元。如果您将一个放在头文件中,然后将该头文件包含在多个翻译单元中,这将导致您的代码中出现多个独立的定义。
这里 VC++ 发生的事情是全局 ourA
已被实例化为指向 main.cpp 中定义的 A
的一个局部定义的指针,然后 local 定义不再可见,但与 notmain.cpp 中当前可见的本地版本不同。 ZN8sunshine4InitEv
的name mangling 区分了独立的定义,但是name mangling 是编译器定义的,我猜想ARM 的RealView 编译器(uVision 使用)有一个不同的方案,无法发现这个错误。
如果这个错误出现在 RealView 中,实际上并不清楚结果是什么,但它不可能是正确的,或者至少是定义明确的。
RealView 实际上在发出其他编译器通常会发出的警告方面相当差,并且在我发现的未定义行为方面有点宽容。始终值得使用其他工具链,例如带有 -Werror -Wall 的 MinGW/GCC 或使用静态分析工具来清理您的代码。
要解决这个问题,您应该使用明确命名的命名空间,或者根本不使用命名空间。
关于c++ - 匿名命名空间在这里导致 undefined reference - 在那里工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22955470/