静态库链接
C++静态库的链接问题。C++静态库(.a)存在重复定义符号(函数)的风险。说明如下:
(1)、在a文件中定义函数f,编译生成a.o
(2)、在b文件中定义同样原型的函数f,实现与a中不同,编译生成b.o
(3)、将a.o,b.o打包到同一个静态库文件c.a
(4)、使用f,并链接c.a,将导致链接到第一个找到的符号。
总结:神坑,不知道怎么填。
异常
请先看下面一段C++代码片段
mutex.lock();
f();
mutex.unlock();
对于上面一段代码,f()需要同步。于是执行前进行加锁操作,执行后解锁。这个一眼看去逻辑很正常。
那么问题在哪儿呢?
异常!
对于C++的异常,熟悉的朋友可能知道对于可能抛出异常的接口调用时,需要用
try
{
}catch()
{
}
进行捕获异常。那么问题是对于一些接口我们有时候并不知道它是否会抛出异常。
但是一旦抛出异常,那么当前函数将终止执行后续代码片段。
并且将异常根据函数调用栈层层返回,直到有一层进行捕获或者终止程序运行。
所有上面的代码,如果f()执行过程中抛出异常,那么mutex.unlock()将不会被执行。
改进方法:利用栈上对象自动回收的机制,让系统进行自动加锁解锁操作。
class A
{
public:
A() { mutex.lock(); }
~A() { mutex.unlock(); }
};
{
A guard;
f();
}
当代码执行到大括号里面时,构造gurad对象进行加锁操作。当执行完f()离开大括号,析构guard对象,解锁。
上面的代码即使f()里面抛出异常,一样会将加锁解锁完整闭环执行完。
内联函数
书上面能找到的这里就不提了。
这里要说的是,当在头文件中声明成员函数,却在多个实现文件中实现(均实现为inline函数)的情况。
这里存在2个问题:
(1)、编译器是否会报告重复定义或者找不到实现?
针对 gcc 版本 4.4.7 20120313 (Red Hat 4.4.7-4) (GCC),测试结果如下。
首先,绝对不会报告重复定义错误。
其次,有可能报告找不到实现。
(2)、如果不会重复定义,那么TMD那到底会使用哪个或者哪些实现呢?
根据情况而定。
看到这里,是不是有种感觉这是在逗你玩的感觉。并非。我的测试demo表明,你实现inline的位置,并非为绑定具体实现到声明的位置。
他(编译器)会在按连接目标文件的次序,当连接到第一个使用该函数的目标文件,从该文件中查找并绑定该函数。之后使用该函数,无论 是否出现其他实现,均不会影响该绑定。
按照此原则,若第一次出现使用该函数时,对应目标文件中无实现,则会报告找不到
实现(基础知识嘛,对吧)。
常量
(1)头文件中可以定义非静态常量,不会出现重复定义错误。编译器会进行折叠优化。