本文地址: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:

 #include "apue.h"

 static void charatatime(char *);

 int main(void)
{
pid_t pid;
TELL_WAIT(); if ((pid = fork()) < ) {
err_sys("fork error");
} else if (pid == ) {
WAIT_PARENT(); /* parent goes first */
charatatime("output from child\n");
} else {
charatatime("output from parent\n");
TELL_CHILD(pid);
}
exit();
} static void charatatime(char *str)
{
char *ptr;
int c; setbuf(stdout, NULL); /* set unbuffered */
for (ptr = str; (c = *ptr++) != ; )
putc(c, stdout);
}

codelist8-7.c

codelist15-3.c:

 #include "apue.h"

 static int    pfd1[], pfd2[];

 void TELL_WAIT(void)
{
if (pipe(pfd1) < || pipe(pfd2) < )
err_sys("pipe error");
} void TELL_PARENT(pid_t pid)
{
if (write(pfd2[], "c", ) != )
err_sys("write error");
} void WAIT_PARENT(void)
{
char c; if (read(pfd1[], &c, ) != )
err_sys("read error"); if (c != 'p')
err_quit("WAIT_PARENT: incorrect data");
} void TELL_CHILD(pid_t pid)
{
if (write(pfd1[], "p", ) != )
err_sys("write error");
} void WAIT_CHILD(void)
{
char c; if (read(pfd2[], &c, ) != )
err_sys("read error"); if (c != 'c')
err_quit("WAIT_CHILD: incorrect data");
}

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

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

查找网上意见如下:

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..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-.c ${apue_error} -o - 成功! 
gcc codelist8-.c codelist15-.c ${apue_error} -o - 成功!!

(完)

参考资料:

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

multiple definition of `err_sys' 《UNIX环境高级编程》的更多相关文章

  1. unix环境高级编程中的err_quit,err_sys用到的知识点

    unix环境高级编程中的err_quit,err_sys 环境 os CentOS release 6.7 (Final) gcc 4.4.7 c语言预备知识 标准输入输出文件 在linux系统中一切 ...

  2. 关于UNIX/Linux下安装《UNIX环境高级编程》源代码的问题

    <UNIX环境高级编程(第三版)>是一本广为人知的unix系统编程书籍. 但是,书中的代码示例,要想正确的编译运行,要先做好准备工作: 1.下载源代码 传送门:http://apueboo ...

  3. unix环境高级编程附录 B 通用代码

    0.说明: 在测试 unix 环境高级编程中的代码时,需要一些作者事先写好的代码, 如: apue.h 包含某些标准系统头文件,定义许多常量及函数原型 还有两个作者自编的函数来对错误进行处理 1.ep ...

  4. Linux - Unix环境高级编程(第三版) 代码编译

    Unix环境高级编程(第三版) 代码编译 本文地址:http://blog.csdn.net/caroline_wendy 时间:2014.10.2 1. 下载代码:http://www.apuebo ...

  5. (十一) 一起学 Unix 环境高级编程 (APUE) 之 高级 IO

    . . . . . 目录 (一) 一起学 Unix 环境高级编程 (APUE) 之 标准IO (二) 一起学 Unix 环境高级编程 (APUE) 之 文件 IO (三) 一起学 Unix 环境高级编 ...

  6. UNIX环境高级编程--#include "apue.h"

    apue.h头文件为作者自己编写而非系统自带,故需要自行添加! 第一:打开网站 http://www.apuebook.com/第二:选择合适的版本(一共有三个版本,根据书的版本选择)下载源码sour ...

  7. apue.h头文件(UNIX环境高级编程)

    在看UNIX环境高级编程是,碰到一个头文件"apue.h",搜一下别人的帖子,其实apue.h是作者自己写的一个文件,包含了常用的头文件,系统不自带.其中包含了常用的头文件,以及出 ...

  8. UNIX环境高级编程——管道读写规则和pipe Capacity、PIPE_BUF

    一.当没有数据可读时O_NONBLOCK disable:read调用阻塞,即进程暂停执行,一直等到有数据来到为止. O_NONBLOCK enable:read调用返回-1,errno值为EAGAI ...

  9. 【UNIX环境高级编程】文件I/O

    [UNIX环境高级编程]文件I/O大多数文件I/O只需要5个函数: open.read.write.lseek以及close 不带缓冲的I/O: 每个read和write都调用内核中的一个系统调用 1 ...

随机推荐

  1. app跳转openURL,兼容方法

    - (void)openScheme:(NSString *)scheme {   UIApplication *application = [UIApplication sharedApplicat ...

  2. Pureftpd

    在lnmp目录下运行./pureftpd.sh 如下:[root@cloud lnmp1.3-full]# 执行./pureftpd.sh 使用命令 Install Pure-FTPd complet ...

  3. 初学c# -- 学习笔记(五) winfrom自定义滚动条

    找了些例子,要么庞大.要么搞个安装组件什么的,我要求能用就行了.实在找例子修改麻烦,就做了一个.其实实现挺简单,就是panel或图片什么的跟着鼠标走就行了. 这里panel自己可以加背景图或直接搞个图 ...

  4. 关于tesseract-ocr3的训练和使用

    众所周知,这是一个出色的字符识别软件.这个开源项目可以在http://code.google.com/p/tesseract-ocr/downloads/list下载. 在使用时,建议使用3而不要使用 ...

  5. [OC笔记]@property之个人理解,大神轻拍

    /** * 一个简单的对象 * * @author suzhen * */ public class SimpleObjcet { /** * 声明一个age字段 */ private Object ...

  6. python 自动发邮件 Errno61 Connection refused

    此问题是在mac机器上遇到 之前在windows平台运行ok的脚本在mac上报错 后来查了半天 发现是网络接入不对 切换下网络后问题就解决了

  7. java项目中build path的设置

    右键点击项目新建文件libs 添加jtds  jar包引用本地动态链接库(dll)的设置方法 配置LibraryJRE的添加和更换  Java项目中build path的设置总结,包括JRE的添加和更 ...

  8. Asp.Net MVC4入门指南(10):第三方控件Studio for ASP.NET Wijmo MVC4 工具应用

    ComponentOne Studio for ASP.NET Wijmo最新版本2013V1支持MVC4,其中包括: 新增 MVC 4 工程模板 (C# & VB) 开箱即用的MVC 4 工 ...

  9. 插入排序 - C语言

    插入排序的思想: 以现有的已排序元素为基础,下一个元素添加到正确的位置,则最终会完成排序. 第一个元素本身是已经排序好的.从第二个开始排. void insertSort(int arr[], int ...

  10. [转]caffe的配置过程

    caffe的配置过程 转:http://blog.csdn.net/brightming/article/details/51106629   版权声明:本文为博主原创文章,欢迎转载!转载请写明原文链 ...