I am reading APUE (Stevens’ “Advanced Programming in the UNIX Environment“), so there is a file “apue.h” which includes some self-definition function declared. I write a file named “wait.c” which defines functions WAIT_CHILD, WAIT_PARENT declared in “apue.h”, and 14.6.c is the main function.
tmp/cciYhMd7.o: In function `err_ret':
14.6.c:(.text+0x0): multiple definition of `err_ret'
/tmp/ccO4WyJS.o:wait.c:(.text+0x0): first defined here
err_ret is just used not defined, so what’s the problem??
wait.c
#include "apue.h"
static volatile sig_atomic_t sigflag;
static sigset_t newmask, oldmask, zeromask;
static void
sig_usr(int signo)
{
sigflag = 1;
}
void
TELL_WAIT(void)
{
if(signal(SIGUSR1, sig_usr) == SIG_ERR)
err_sys("signal(SIGUSR1) error");
if(signal(SIGUSR2, sig_usr) == SIG_ERR)
err_sys("signal(SIGUSR2) error");
sigemptyset(&zeromask);
sigemptyset(&newmask);
sigaddset(&newmask, SIGUSR1);
sigaddset(&newmask, SIGUSR2);
if(sigprocmask(SIG_BLOCK, &newmask, &oldmask) < 0)
err_sys("SIG_BLOCK error");
}
void
TELL_PARENT(pid_t pid)
{
kill(pid, SIGUSR2);
}
void
WAIT_PARENT(void)
{
while(sigflag == 0)
sigsuspend(&zeromask);
sigflag = 0;
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
}
void
TELL_CHILD(pid_t pid)
{
kill(pid, SIGUSR2);
}
void
WAIT_CHILD(void)
{
while(sigflag == 0)
sigsuspend(&zeromask);
sigflag = 0;
if(sigprocmask(SIG_SETMASK, &oldmask, NULL) < 0)
err_sys("SIG_SETMASK error");
}
The code above is my “wait.c” source file. I just use err_sys. Below is the linking command line and the linker error messages I’m getting:
$ gcc -o a.out wait.c 14.6.c
/tmp/ccZ5F3Pn.o: In function `err_ret':
14.6.c:(.text+0x0): multiple definition of `err_ret'
/tmp/cc5EXGbf.o:wait.c:(.text+0x0): first defined here
/tmp/ccZ5F3Pn.o: In function `err_sys':
14.6.c:(.text+0x38): multiple definition of `err_sys'
/tmp/cc5EXGbf.o:wait.c:(.text+0x38): first defined here
/tmp/ccZ5F3Pn.o: In function `err_exit':
14.6.c:(.text+0x76): multiple definition of `err_exit'
/tmp/cc5EXGbf.o:wait.c:(.text+0x76): first defined here
/tmp/ccZ5F3Pn.o: In function `err_dump':
14.6.c:(.text+0xaf): multiple definition of `err_dump'
/tmp/cc5EXGbf.o:wait.c:(.text+0xaf): first defined here
/tmp/ccZ5F3Pn.o: In function `err_msg':
14.6.c:(.text+0xe6): multiple definition of `err_msg'
/tmp/cc5EXGbf.o:wait.c:(.text+0xe6): first defined here
/tmp/ccZ5F3Pn.o: In function `err_quit':
14.6.c:(.text+0x116): multiple definition of `err_quit'
/tmp/cc5EXGbf.o:wait.c:(.text+0x116): first defined here
/tmp/ccZ5F3Pn.o: In function `TELL_WAIT':
14.6.c:(.text+0x5fe): multiple definition of `TELL_WAIT'
/tmp/cc5EXGbf.o:wait.c:(.text+0x272): first defined here
/tmp/ccZ5F3Pn.o: In function `TELL_CHILD':
14.6.c:(.text+0x72e): multiple definition of `TELL_CHILD'
/tmp/cc5EXGbf.o:wait.c:(.text+0x3a2): first defined here
/tmp/ccZ5F3Pn.o: In function `WAIT_PARENT':
14.6.c:(.text+0x6d8): multiple definition of `WAIT_PARENT'
/tmp/cc5EXGbf.o:wait.c:(.text+0x34c): first defined here
/tmp/ccZ5F3Pn.o: In function `TELL_PARENT':
14.6.c:(.text+0x6bd): multiple definition of `TELL_PARENT'
/tmp/cc5EXGbf.o:wait.c:(.text+0x331): first defined here
/tmp/ccZ5F3Pn.o: In function `WAIT_CHILD':
14.6.c:(.text+0x749): multiple definition of `WAIT_CHILD'
/tmp/cc5EXGbf.o:wait.c:(.text+0x3bd): first defined here
collect2: ld returned 1 exit status
The source from the APUE book’s web site has these three declarations (amongst many others) in
apue.h:Judging from the error message from your compiler, not only is
err_ret()defined, it is in fact defined twice, once in your source filewait.cand once in your source file14.6.c. You will need to decide which (if either) of those definitions is correct, and remove the other, or decide that you can’t use the code inwait.cwith your program in14.6.c. It might be better still to puterr_ret()and friends into their own source file. In the source, theerr_*()functions are inlib/error.c.If your TU (translation unit) does
#include "lib/error.c", then your TU is defining the functions. The C compiler sees the source code containing your source plus the headers you include plus (hypothetically) the code inlib/error.c. You simply shouldn’t be including that source file; you should compile it separately and link the object file into your program. Theapue.hheader declares theerr_*()functions so you can use them in your code. You are expected to compilelib/error.cseparately and link it with yourwait.oand14.6.ofiles.It is crucial to understand the difference between defining a variable or function (actually allocating the storage for it) and declaring a variable or function (telling the compiler that the function or variable exists, but that it is not defined here — as in ‘this declaration does not define it’, even if the next line in the source file does define it). Headers should provide declarations and should not provide definitions (most of the time — it’s a good enough rule for now, until you know enough to know when and how to break the rule).
So, it sounds like you need three source files in your compile and link line:
Or you might do it in separate operations:
You might need extra compiler flags (
-Ior-Doptions for example), or extra libraries and linker options (-lliband-L /directory/liboptions, for example).If your source files 14.6.c and wait.c contain
#include "apue.h"and do not include other source files (so no#include "lib/error.c"or anything similar — and14.6.cdoes not include yourwait.cnor vice versa), then you should not run into problems.However, you are running into problems, and we can’t see your source or your linking command, which means we have to try and guess what you’ve done wrong. We can devise all sorts of outlandish examples of what you might be doing, but we’re most likely to be wrong.
So, keeping the code to a minimum, show us which files you are compiling and how you are compiling them.