《UNIX环境高级编程》multiple definition of `err_sys',errsys


本文地址:http://www.cnblogs.com/yhLinux/p/4079930.html

 

问题描述:

[点击此处直接看解决方案]

在练习《UNIX环境高级编程》APUE程序清单8-7的时候,codelist8-7.c中用到了codelist15-3.c中的函数TELL_WAIT(),WAIT_PARENT()及TELL_CHILD()。

codelist8-7.c:

1 #include "apue.h" 2 3 static void charatatime(char *); 4 5 int main(void) 6 { 7 pid_t pid; 8 TELL_WAIT(); 9 10 if ((pid = fork()) < 0) { 11 err_sys("fork error"); 12 } else if (pid == 0) { 13 WAIT_PARENT(); /* parent goes first */ 14 charatatime("output from child\n"); 15 } else { 16 charatatime("output from parent\n"); 17 TELL_CHILD(pid); 18 } 19 exit(0); 20 } 21 22 static void charatatime(char *str) 23 { 24 char *ptr; 25 int c; 26 27 setbuf(stdout, NULL); /* set unbuffered */ 28 for (ptr = str; (c = *ptr++) != 0; ) 29 putc(c, stdout); 30 } codelist8-7.c

codelist15-3.c:

1 #include "apue.h" 2 3 static int pfd1[2], pfd2[2]; 4 5 void TELL_WAIT(void) 6 { 7 if (pipe(pfd1) < 0 || pipe(pfd2) < 0) 8 err_sys("pipe error"); 9 } 10 11 void TELL_PARENT(pid_t pid) 12 { 13 if (write(pfd2[1], "c", 1) != 1) 14 err_sys("write error"); 15 } 16 17 void WAIT_PARENT(void) 18 { 19 char c; 20 21 if (read(pfd1[0], &c, 1) != 1) 22 err_sys("read error"); 23 24 if (c != 'p') 25 err_quit("WAIT_PARENT: incorrect data"); 26 } 27 28 void TELL_CHILD(pid_t pid) 29 { 30 if (write(pfd1[1], "p", 1) != 1) 31 err_sys("write error"); 32 } 33 34 void WAIT_CHILD(void) 35 { 36 char c; 37 38 if (read(pfd2[0], &c, 1) != 1) 39 err_sys("read error"); 40 41 if (c != 'c') 42 err_quit("WAIT_CHILD: incorrect data"); 43 } View Code

在使用命令编译8-7时,提示以下错误:

$ gcc codelist8-7.c codelist15-3.c -o 8-7
/tmp/ccMDAwpv.o: In function `err_ret':
codelist15-3.c:(.text+0x0): multiple definition of `err_ret'
/tmp/ccXi2EPL.o:codelist8-7.c:(.text+0x0): first defined here
/tmp/ccMDAwpv.o: In function `err_sys':
codelist15-3.c:(.text+0xa9): multiple definition of `err_sys'
/tmp/ccXi2EPL.o:codelist8-7.c:(.text+0xa9): first defined here
/tmp/ccMDAwpv.o: In function `err_exit':
codelist15-3.c:(.text+0x15a): multiple definition of `err_exit'
/tmp/ccXi2EPL.o:codelist8-7.c:(.text+0x15a): first defined here
/tmp/ccMDAwpv.o: In function `err_dump':
codelist15-3.c:(.text+0x209): multiple definition of `err_dump'
/tmp/ccXi2EPL.o:codelist8-7.c:(.text+0x209): first defined here
/tmp/ccMDAwpv.o: In function `err_msg':
codelist15-3.c:(.text+0x2b5): multiple definition of `err_msg'
/tmp/ccXi2EPL.o:codelist8-7.c:(.text+0x2b5): first defined here
/tmp/ccMDAwpv.o: In function `err_quit':
codelist15-3.c:(.text+0x360): multiple definition of `err_quit'
/tmp/ccXi2EPL.o:codelist8-7.c:(.text+0x360): first defined here
collect2: ld 返回 1

查找网上意见如下:

1. http://bbs.chinaunix.net/thread-3699788-1-1.html

    我想是不是因为我在apue.h头文件中,添加了#include "error.c",虽然apue.h中

    #ifndef __APUE_H__
    #define __APUE_H__

复制代码
但是编译器对每个文件是分别编译的,所以在文件wait.c和14.6.c中都#include "apue.h",就会包含两份error.c文件,
而在error.c文件中是函数的定义(并不是声明),所以才会出现这样的情况。 所以我删除在apue.h中#include
"error.c",makefile文件如下: inc=/home/lee/program/apue/apue.2e/include/ error=/home/lee/program/apue/apue.2e/include/error.c a.out:14.6.c wait.c gcc -I $(inc) -o a.out 14.6.c wait.c $(error) 复制代码 apue.h文件中/home/lee/program/apue/apue.2d/include/目录下。 这样就没有问题了。 不知是不是如我想的这样。

#没错,而且没有充分理由时尽量不要 include c 文件

以上这条讨论讲得比较到位吧,原来,我之前按这篇文章的方法[http://blog.csdn.net/quan9ing007/article/details/9929659此方法不好]把 apue.herror.h 都拷贝到 /usr/include 文件夹下了。

其实按上面的说法,不该把在apue.h中#include "error.c",并把 error.c 放到 /usr/include 目录下的,在每一次编译时添加error.c就好。

 

解决方案(推荐)

因此,只把 apue.h 放到/usr/include目录下,而由于要经常用到error.c,我们将定义一个error环境变量,这样就不必每次都把error.c拷贝到相关文件夹下参与编译。

这里假定当前用户是Lee,error.c存放在/home/Lee/code_Lee/APUE/part_of_source/:

sudo cp /home/Lee/code_Lee/APUE/part_of_source/apue.h /usr/include/apue.h

sudo chmod a+r /usr/include/apue.h

vi /home/Lee/.bashrc 在.bashrc文末添加apue_error变量:

  apue_error=/home/Lee/code_Lee/APUE/part_of_source/error.c

source ~/.bashrc      /* 这很重要,一定要执行 */

echo ${apue_error}

  /home/Lee/code_Lee/APUE/part_of_source/error.c

gcc codelist8-6.c ${apue_error} -o 8-6 成功! 
gcc codelist8-7.c codelist15-3.c ${apue_error} -o 8-7  成功!!

 

(完)

参考资料:

1. Linux的环境变量

   http://www.cnblogs.com/Neddy/archive/2011/03/01/1968018.html

2. linux环境变量(转)

   http://www.cnblogs.com/growup/archive/2011/07/02/2096142.html


makefile编写问题:multiple definition of

在RMB.o里有一个rmb_chk_str与你的testRMB.o中的定义重复了,看一下,是哪个定义错了

makefile里看着怪的就是:$CC $(LIBFLAGS) $? -o $@ $(LIBS1) 这句,改成以下的试试
$CC $? -o $@ $(LIBFLAGS) $(LIBS1)
 

c语言中 multiple definition of 'main'

那你是不是在同一个工程的其他文件中也定义了main函数呢?如果是,那肯定是错误的;

一个工程只能有一个main函数,你可以将其他文件的main函数改一下名字
 

相关内容