链接的 multiple definition错误

2990阅读 0评论2013-01-27 lzj123
分类:C/C++

有如下几个文件
lib.c:
#include 

int a()
{
    printf("lib in %s\\n", __func__);
    return 0;
} 

int b()
{
    printf("lib in %s\\n", __func__);
    return 0;
} 

int c()
{
    printf("lib in %s\\n", __func__);
    return 0;
} 

lib.h:

#ifndef _LIB_H_
#define _LIB_H_

int a();
int b();
int c();

#endif


c.c:

#include 

int c()
{
    printf("in %s\\n", __func__);
    return 0;
} 

c.h:

#ifndef _C_H_
#define _C_H_

int c();

#endif


t.c:

#include "t.h"
#include 

int t()
{
    printf("in %s start.\\n", __func__);
    printf("in %s end.\\n", __func__);
    return 0;
} 


t.h:
#ifndef _O_H_
#define _O_H_

int t();

#endif


main.c:

#include 
#include 
#include 

int main(int argc, char *argv[ ])  
{
    c();
    t();
    //a();
    return 0; 
} 

c.c文件和lib.c文件中都有函数c()。

下面是Makefile的内容。
SRCS=t.c c.c main.c 
OBJS=$(SRCS:.c=.o) 

.c.o:
    gcc -I. -c $<

m:$(OBJS) liblib.a 
    gcc -o $@ -I. -L. $(OBJS) -llib 

liblib.a:lib.o
    ar -cr liblib.a lib.o

clean:
    -rm $(OBJS) lib.o liblib.a m


如果main函数中没有调用liblib.a中的函数a(),则根据Makefile可以正常进行编译链接。
如下所示:
lzj@lzj-Inspiron-560s:~/study/test/test_lib$ make
gcc -I. -c t.c
gcc -I. -c c.c
gcc -I. -c main.c
gcc -I. -c lib.c
ar -cr liblib.a lib.o
gcc -o m -I. -L. t.o c.o main.o -llib 

如果将main函数中对函数a()的调用的屏蔽去掉,则链接时就会出现函数c()重复定义的错误。
如下所示:
lzj@lzj-Inspiron-560s:~/study/test/test_lib$ make
gcc -I. -c t.c
gcc -I. -c c.c
gcc -I. -c main.c
gcc -I. -c lib.c
ar -cr liblib.a lib.o
gcc -o m -I. -L. t.o c.o main.o  -llib 
./liblib.a(lib.o): In function `c':
lib.c:(.text+0x44): multiple definition of `c'
c.o:c.c:(.text+0x0): first defined here
collect2: ld 返回 1
make: *** [m] 错误 1

由以上结果可以知道,链接器在链接时是优先查找目标文件中的函数,目标文件中
不存在时才会去静态库中查找。
既使调用的函数在目标文件和静态库中同时存在,只要没有调用只在静态库中存在的函数,
那么也会优先链接目标文件中的函数,而不会报函数重定义的错误。
另外,上面的结果与链接时的顺序也没有关系(静态库在目标文件的前面或后面)。
gcc -o $@ -I. -L. $(OBJS) -llib 和 gcc -o $@ -I. -L. -llib $(OBJS)

的执行结果是一样的。


另外,如果函数a()在另一个目标文件(比如a.o)中,并且这个文件与lib.o不在同一目录,

由a.o和lib.o生成静态库liblib.a,这样即使在main函数中调用函数a(),链接也能正常进行而不会报

函数c()重定义的错误。


上一篇:isdigit的使用
下一篇:Makefile备忘