zoukankan      html  css  js  c++  java
  • multiple definition of `err_sys' 《UNIX环境高级编程》

    本文地址: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
    ");
    15     } else {
    16         charatatime("output from parent
    ");
    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

  • 相关阅读:
    Hibernate框架配置
    单利模式的数据库工具类
    EL
    JSP内置对象---request和 response
    模拟淘宝使用cookie记录登录名,
    模拟操作银行登入页面。
    jsp...九九乘法表,三角形,菱形
    jdbc模拟电话本。
    22.编写一个类A,该类创建的对象可以调用方法showA输出小写的英文字母表。然后再编写一个A类的子类B,子类B创建的对象不仅可以调用方法showA输出小写的英文字母表,而且可以调用子类新增的方法showB输出大写的英文字母表。最后编写主类C,在主类的main方法 中测试类A与类B。
    机动车
  • 原文地址:https://www.cnblogs.com/yhLinux/p/4079930.html
Copyright © 2011-2022 走看看