【问题标题】:Wrong symbol defined in shared library with 'using namespace'使用“使用命名空间”在共享库中定义的错误符号
【发布时间】:2019-09-06 14:01:06
【问题描述】:

根据是否使用using 指令,我在共享库中定义了不同的符号。我想知道我做错了什么/为什么这种方法不起作用。

对于这个例子,我正在从源文件util.cpp 创建一个共享库libutil.so,其中包括一个标题util.hpp。链接到libutil.so 的程序在prog.cpp 中定义。

// util.h
#pragma once
namespace util {
int func();
}

// util.cpp
#include "util.hpp"

using namespace util; // This is the directive in question
int func() { return 42; }
// prog.cpp
#include "util.hpp"
#include <iostream>

int main() {
  std::cout << util::func() << std::endl;
}

这是我编译和链接所有内容的方法(在 gcc-7.3.0 上)

g++ -g -std=c++14 -fPIC -o util.o -c util.cpp
g++ -g -std=c++14 -shared -o libutil.so util.o 
g++ -g -std=c++14 -o prog prog.cpp -L. -lutil

导致此错误的最后一行

/tmp/ccwaFRtS.o: In function `main':                                  
/home/wtf/prog.cpp:5: undefined reference to `util::func()'
collect2: error: ld returned 1 exit status                            

但是,将 util.cpp 更改为此可以修复错误:

namespace util {
int func() { return 42; }               
}               

在检查符号表时,原始(损坏的)方式显示如下:

000000000000059a T _Z4funcv

而第二种方法(正确定义)显示了这一点:

000000000000059a T _ZN4util4funcEv

【问题讨论】:

  • 想一想:使用(不良做法)using 方法,编译器如何知道您正在尝试定义 util::func 而不是 ::func?
  • 另一种选择是将func定义更改为int util::func() { return 42; }

标签: c++ linker


【解决方案1】:

在您的 .cpp 文件中,类似这样的代码:

using namespace util;

void f() { }

做两件事:

  • 使命名空间util 中的符号可见
  • 在全局命名空间中定义函数f()

另一方面,

namespace util {
    void f() { }
}

在命名空间 util 中定义函数 f()。

因此,第一个版本未定义 util::f,因此您最终会出现链接错误。

【讨论】:

  • 啊当然,using 指令只适用于名称 lookup 而不是定义。现在有道理了。谢谢!
【解决方案2】:

使用namespace util {...}的正确方法导出来自编译单元util.cpp的符号,而using namespace util;只是告诉编译器在该命名空间中查找名称。

编辑:在前者中,您基本上在全局命名空间::func() 中定义了函数。

进一步了解全局和匿名(未命名)命名空间之间的区别。

// file.cc
namespace {
int func() {}
}  // namespace

将仅在此编译单元中可见(内部链接),而不是全局可见性(外部链接),如

// file.cc
int func() {}

【讨论】:

  • 它不是匿名命名空间。它是全局命名空间。
猜你喜欢
  • 2011-02-28
  • 2013-05-20
  • 2021-03-08
  • 2011-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多