apue:Advanced Programming in the UNIX Environment,
本文关注第三版(3e)
1. apue.3e 的安装
第三版较之第二版有了很大改变,安装更为简单。
(2)解压:tar -zxvf
(3)cd apue.3e/
(4)make
在这个过程中,你会看到最后由于can’t find -lbsd 而不能 make成功,解决办法是添加 libbsd.a 的静态链接库:
sudo apt-get install libbsd-dev
(5)再次 make
(6)在编译成功的基础上,我们进行安装apue.h文件及其对应的静态链接库libapue.a
sudo cp ./include/apue.h /usr/include/ sudo cp ./lib/libapue.a /usr/local/lib/
2. : undefined reference to `err_quit’
我们在编写本书的第一个程序:myls.c 时,纵然按照第一节将 apue.3e 安装完成,在编译时,仍然会提示如下的错误:
: undefined reference to `err_quit'
: undefined reference to `err_sys'
解决方法:
因为err_quit 跟 err_sys 是作者自己定义的错误处理函数,需要单独定义头文件,在/usr/include 下新建一个名为 myerr.h 的文件,内容为:
#include "apue.h"
#include <errno.h> /* for definition of errno */
#include <stdarg.h> /* ISO C variable aruments */
static void err_doit(int, int, const char *, va_list);
/*
* Nonfatal error related to a system call.
* Print a message and return.
*/
void
err_ret(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(1, errno, fmt, ap);
va_end(ap);
}
/*
* Fatal error related to a system call.
* Print a message and terminate.
*/
void
err_sys(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(1, errno, fmt, ap);
va_end(ap);
exit(1);
}
/*
* Fatal error unrelated to a system call.
* Error code passed as explict parameter.
* Print a message and terminate.
*/
void
err_exit(int error, const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(1, error, fmt, ap);
va_end(ap);
exit(1);
}
/*
* Fatal error related to a system call.
* Print a message, dump core, and terminate.
*/
void
err_dump(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(1, errno, fmt, ap);
va_end(ap);
abort(); /* dump core and terminate */
exit(1); /* shouldn't get here */
}
/*
* Nonfatal error unrelated to a system call.
* Print a message and return.
*/
void
err_msg(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(0, 0, fmt, ap);
va_end(ap);
}
/*
* Fatal error unrelated to a system call.
* Print a message and terminate.
*/
void
err_quit(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
err_doit(0, 0, fmt, ap);
va_end(ap);
exit(1);
}
/*
* Print a message and return to caller.
* Caller specifies "errnoflag".
*/
static void
err_doit(int errnoflag, int error, const char *fmt, va_list ap)
{
char buf[MAXLINE];
vsnprintf(buf, MAXLINE, fmt, ap);
if (errnoflag)
snprintf(buf+strlen(buf), MAXLINE-strlen(buf), ": %s",
strerror(error));
strcat(buf, " ");
fflush(stdout); /* in case stdout and stderr are the same */
fputs(buf, stderr);
fflush(NULL); /* flushes all stdio output streams */
}
接下来在 myls.c 里面引用#include
gcc myls.c
./a.out /home
就可以看到 home 目录下面的内容了。