匿名命名空间在这里导致未定义的引用 - 在那里工作

时间:2014-04-09 07:18:16

标签: c++ gcc g++ embedded keil

我为嵌入式系统编写了一些C ++代码,它就像一个魅力。当前任务是模拟此设备在PC上的行为。一些代码必须被移植:对于第一个测试,我使用mingw(g ++),而嵌入式系统是STM32并使用KEILμVision工具链。

我遇到了一个与功能行为无关的问题,而不是编译器特有的怪异问题。我在匿名命名空间中定义了2个类,因为它们包含在整个项目中。现在在嵌入式设备上编译并运行没有问题。 g ++抱怨未定义的引用!

当我删除类的匿名命名空间时,它会编译并运行!但为什么?以下是一些重现情况的示例代码: 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

theclass.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 **     信息:内部构建器用于构建     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 to ourA'中     collect2.exe:错误:ld返回1退出状态

09:09:57 Build Finished (took 702ms)

删除该命名空间可以解决问题,但为什么要编译,链接,在KEIL中工作?任何人都可以向我解释这个吗?

1 个答案:

答案 0 :(得分:0)

我建议这是滥用匿名命名空间功能。它与你想要实现的完全相反。

匿名命名空间用于将定义本地化为单个翻译单元。如果将一个放在头文件中,则将该头包含在多个转换单元中,这将导致代码中出现多个独立定义。

这里发生的事情VC ++是一个全局ourA已被实例化为指向main.cpp中定义的A的一个本地定义的指针,然后是 local 定义不再可见,但与notmain.cpp中当前可见的本地版本不同。名称重整ZN8sunshine4InitEv区分独立定义,但名称重整是编译器定义的,我猜ARM的RealView编译器(由uVision使用)有一个不同的方案,无法发现此错误。

实际上不清楚RealView中出现此错误的结果是什么,但它不能正确或至少定义得很好。

实际上,RealView在发出其他编译器正常发出的警告方面相当差,而且在我发现的未定义行为方面有点宽容。总是值得使用另一个工具链,例如MinGW / GCC和-Werror -Wall,或者使用静态分析工具来清理代码。

要解决此问题,您应该使用显式命名的命名空间,或者根本不使用命名空间。