[Bug] g++4.6 参数顺序

遇到一个bug, 看起来像是g++-4.6的问题。

问题是这样的。这个源文件用到了OpenCV:

//< file: test.cpp
#include 

int main (int argc, char** argv) {
    cv::Mat image;
    return 0;
}

用这样一行命令编译:

g++-4.6 `pkg-config --libs opencv`  -o test.bin test.cpp

遇到了错误:

/tmp/ccs2MlQz.o: In function `cv::Mat::~Mat()':
test.cpp:(.text._ZN2cv3MatD2Ev[_ZN2cv3MatD5Ev]+0x39): undefined reference to `cv::fastFree(void*)'
/tmp/ccs2MlQz.o: In function `cv::Mat::release()':
test.cpp:(.text._ZN2cv3Mat7releaseEv[cv::Mat::release()]+0x47): undefined reference to `cv::Mat::deallocate()'
collect2: ld returned 1 exit status

错误的原因应该是g++没有正确的链接到OpenCV的库。各种尝试之后发现只要调换一下参数的位置就可以正常编译 -_-!!
改用这样一行命令编译就没有问题了。

g++-4.6 test.cpp `pkg-config --libs opencv`  -o test.bin

具体原因不明,但是如果把g++-4.6换作g++-4.4就没有这个问题。
这行命令也可以正常编译:

g++-4.4 `pkg-config --libs opencv`  -o test.bin test.cpp 

这么看起来很有可能是g++-4.6的bug,或者是改进..?

静态链接库

静态链接库

几个例子,使用和建立静态库的时候的几种常见情景。

首先建几个文件
a.h

void testA();

a.c

#include "a.h"

void testA() {
    printf("A");
}

b.h

void testB();

b.c

#include "b.h"
#include "a.h"

void testB(){
    testA();
    printf("B");
}
  1. 得到目标文件
  2. $gcc -c a.c
    
    $gcc -c b.c
    
  3. 得到静态库文件
  4. $ ar -r libba.a a.o b.o
    
    $ ar -r liba.a a.o
    
    $ ar -r libb.a b.o
    

得到了库libba.a libb.a liba.a

这是最终需要完成的程序。
test.c

#include "b.h"
void main()
{
    testB();
}

假设我们没有a.c,b.c这两个源文件。
在这种情况下,为了编译test.c得到可执行文件,至少需要那些文件?

由于b.h中包含了a.h,所以两个头文件都是需要的。

  1. 用libba.a
  2. $ gcc test.c -o test -L. -lba
    

    我们需要的是testB()和testA()的实现,libba.a里显然有这些实现,所以是可行的。

  3. 用libb.a 和 liba.a
  4. $ gcc test.c -o test -L. -lb -la
    

如果一开始就没有a.c,怎么办?
假设liba.a是一个第三方的闭源库,我们只有liba.a和a.h
当然,为了得到test这个可执行文件,我们也可以使用上面第二种方式编译。

如果我们不是要得到test,而是要为其它人提供libb.a怎么办?
上面的libb.a只含有testB()的实现,而没有testA()的实现。
除非“其它人”也有liba.a,否则只用libb.a是没有办法使用testB()这个函数的。

那么是不是可以把liba.a链入libb.a?
对于静态库来说,是可以的。这也就是我们的解决办法。
-r 告诉Linker进行增量式链接,得到二进制目标文件,而不是最终的可执行文件。

$ ar -r libnba.a ba.o

这个libnba.a和前面通过

$ ar -r libba.a a.o b.o

得到的libba.a应该是一样的。

这时我们就可以把libnba.a提供给”其它人”了。

$ gcc test.c -o test -L. -lnba

可以得到test可执行文件。