由一个链接错误想到的

原创 2012年03月22日 22:13:48


假设有两个模块A 和B, A有两个文件 libClass.h, libClass.cpp; B有两个文件, libClient.h, libClient.cpp.

代码如下:

libClass.h:

#ifndef __LIBCLASS_H__
#define __LIBCLASS_H__

class MyTest
{
public:
static bool Foo(int a, char c);
};
#endif //ifndef __LIBCLASS_H__

libClass.cpp:

#include "libClass.h"
bool MyTest::Foo(int a, char c)
{
	return false;
}

libClient.h:

#ifndef __LIBCLIENT_H__
#define __LIBCLIENT_H__
class ClientClass
{
public:
void TestFoo(void);
};
#endif//__LIBCLIENT_H__

libClient.cpp:

#include "libClient.h"
#include "libClass.h"

void ClientClass::TestFoo(void)
{
	int a = 10;
	char c = 's';
	MyTest::Foo(a, c);	
}

最后是一个测试程序 test.cpp:

#include "libClient.h"
int main(void)
{
	ClientClass client;
	client.TestFoo();
	return 0;
}

在命令行分别把两个类文件编到两个静态库里面:

g++ -c libClass.cpp

ar rv libClass.a libClass.o

g++ -c libClient.cpp

ar rv libClient.a libClient.o

最后编译测试程序:

g++ test.cpp libClient.a libClass.a

没有问题。


现在,改一下 第一个类的接口:

libClass.h:

#ifndef __LIBCLASS_H__
#define __LIBCLASS_H__

class MyTest
{
public:
static bool Foo(int a, char c, long *p = 0);
};
#endif //ifndef __LIBCLASS_H__

libClass.cpp:

#include "libClass.h"
bool MyTest::Foo(int a, char c, long *p)
{
	return false;
}

重新编译一下:

g++ -c libClass.cpp

ar rv libClass.a libClass.o

然后,编译测试程序:

g++ test.cpp libClient.a libClass.a

libClient.a(libClient.o): In function `ClientClass::TestFoo()':
libClient.cpp:(.text+0x20): undefined reference to `MyTest::Foo(int, char)'
collect2: ld returned 1 exit status


说起来应该不发生错误才对,因为增加的只是一个函数的默认参数,client 代码不用修改。

但是从错误信息来看,另一类生成的目标代码已经记忆了原来的类的接口信息,所以如果不更新另一个类的目标代码,链接惠出错。

我们检查一下 libClient.o 的符号表:

charles@China:/WinD/Code/myTest$ nm -C libClient.o

00000000 T ClientClass::TestFoo()
         U MyTest::Foo(int, char)
         U __gxx_personality_v0

果然,client目标代码里面的函数 Foo()符号还是修改之前的那个。现在这个函数接口参数已经被修改了,所以会发生错误。

现在重新编译 libClient.cpp:

rm libClient.o
cc -c libClient.cpp
ar rv libClient.a libClient.o

然后, 再检查一下符号表:

charles@China:/WinD/Code/myTest$ nm -C libClient.o 
00000000 T ClientClass::TestFoo()
         U MyTest::Foo(int, char, long*)
         U __gxx_personality_v0

现在,  client的符号表更新了。然后再链接,就没有问题。


由此得出一个结论,使用静态链接的时候,如过一个模块的接口(或者全局变量)有变更,除了该模块要重新编译外,其他依赖于这个模块的代码也要重新编译。

相关文章推荐

关于链接过程中出现的“找到一个或多个多重定义的符号”和“无法解析的外部符号”错误的探究

不妨先看一个例子: //A.h #pragma once #include "B.h" class A { public: A(void); ...

关于链接错误的一个罕见原因

一个常见的链接错误,一个罕见的原因。层层分析,抽丝剥茧,终于水落石出。...

(转载+心得) 关于添加了一个lib之后的链接错误2005

今天本想把在游戏中用到的FreeType字体的使用给总结一下,写一个Demo出来的.郁闷的事发生了,用vs2008建了一个空项目,装FreeType相关的一些代码给copy整理出来后,编译后Link是...

从一个链接错误探究GCC的链接库顺序

作者:朱金灿来源:http://blog.csdn.net/clever101           使用CodeBlocks10.05编一个小程序用到了png库和zlib库。我发现编译png静态库时,...

校园宽带常见的链接错误

  • 2011年11月14日 14:57
  • 7KB
  • 下载

日常 myeclipse链接VisualSVNServerShell 的错误

svn 一个开源代码控制系统 (集中式) git (目前最多人用的)开源控制系统还有cvs 等。(分布式) ----每一次的修改都会被记录下来,方便查询每个人的修改 ----(服务器下载与提交冲突) ...

链接错误LNK2001

  • 2012年08月26日 16:01
  • 15KB
  • 下载

科讯CMS的热搜TAGS里的内容链接错误

看很多用科汛CMS的朋友遇到了这个问题,把解决方法分享一下,希望对遇到问题的朋友们可以参考一下。 1,进入后台——>设置——>基本设置——>基本信息设置 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:由一个链接错误想到的
举报原因:
原因补充:

(最多只允许输入30个字)