如何让gcc报告未定义的,未使用的外部符号的错误

时间:2014-07-12 18:19:02

标签: c++ gcc linker

我正在寻找一种在声明函数时产生链接器错误的方法 但未在导出的类中定义。这是一个简单的例子 说明了问题:

test.h:

#define DLLEXPORT __attribute__((__visibility__("default")))

class DLLEXPORT CLASS_A {
public:
     CLASS_A();
    ~CLASS_A();
    void withdefinition();
    void nodefinition();
};

TEST.CPP:

#include "test.h"

CLASS_A::CLASS_A() {}
CLASS_A::~CLASS_A() {}
void CLASS_A::withdefinition() {}

生成文件:

CFLAGS = -Wall -Wextra -fvisibility=hidden -fvisibility-inlines-hidden -fPIC
LDFLAGS = -Wl,--no-undefined

top: test.so

test.o: test.cpp test.h Makefile
    g++ $(CFLAGS) -c $< -o $@
    nm -C test.o

test.so: test.o
    g++ -shared $(CFLAGS) $(LDFLAGS) $< -o $@
    nm -C test.so

我从“nm test.o”看到的输出如下:

nm -C test.o
0000000000000014 T withdefinition()
0000000000000000 T CLASS_A::CLASS_A()
0000000000000000 T CLASS_A::CLASS_A()
000000000000000a T CLASS_A::~CLASS_A()
000000000000000a T CLASS_A::~CLASS_A()

函数“withdefinition()”生成外部定义,而函数“nodefinition()”根本不生成符号。理论上,如果test.cpp的编译可以为“nodefinition”生成未定义的符号,则后续的链接命令会抱怨未定义的符号。不幸的是,只有在代码中显式调用“nodefinition()”时才会发生这种情况。这是一个在重构过程中通常会出现的错误,如果可以尽早检测到它会有所帮助 - 是否有一种简单的方法可以使用gcc工具链自动执行此操作?

2 个答案:

答案 0 :(得分:1)

声明但未定义的(非虚拟)函数在编译的代码中不产生任何跟踪。这是设计的。你无法改变它,因为这样的改变绝对会破坏一切。

想象一下每个功能,每个课程,每一个数据,你在标准include文件中没有任何东西,你不会使用,不关心和不关心。甚至知道它存在,在你的编译代码中留下一个符号。

答案 1 :(得分:0)

由于编译器实际上并不知道您在哪里定义哪些函数,因此编译器/链接器无法执行此任务。

请注意,在编译阶段可能存在可能存在名为nodefinition的函数的知识,因此只有在实际使用该函数时才会保留此信息。

如果您有严格的&#34; x.h&#34;你可以使用clang分析框架编写一些(或找到其他人已经编写的)代码分析工具。和&#34; x.cpp&#34;关系,因此没有在&#34; x.h&#34;中声明的功能永远在另一个文件中定义,而不是&#34; x.cpp&#34; (或#34; x.cpp&#34所包含的文件;)。但是如果在其他地方允许实现,那么它只能检测链接器实际需要该函数的时间。

当然,在大多数情况下,代码审查也应该抓住这类问题。