I have a program written in c which uses the execvpe(3) function, and I've got a line set to include the requisite header file:
#include <unistd.h>
I compile this file with the following command...
gcc foo.c -o foo
...only to get the following warning:
warning: implicit declaration of function ‘execvpe’ [-Wimplicit-function-declaration]
I've encountered similar behavior with files that reference the pthread_create(3) function. The difference is obviously that whereas the pthread_create(3) man page clearly states that one should "Compile and link with -pthread", the man page for the exec(3) family of functions does not have any such instructions. Furthermore, I cannot find any reference in the manual or online to an analogous compiler flag for the exec(3) family.
I'd appreciate any information you have on this matter. If there is some flag I should be using at compile time, or if I am looking in entirely the wrong place for a solution, please let me know.
The man page here states that it is necessary to define the _GNU_SOURCE feature test macro to enable the function declaration:
#define _GNU_SOURCE
#include <unistd.h>
Interestingly however the link to unistd.h on the same man page takes you to an implementation that does not declare execvpe at all. You could check your system's unistd.h file to check that it is declared and is dependent on _GNU_SOURCE - that is to solve this an similar problems in the future - check the header content to see if it is even there and what macros it may depend on.
If it is not in the header file, then it is most probably also not in the library, but you could check as follows:
#include <unistd.h>
extern int execvpe(const char *file, char *const argv[], char *const envp[]);
which will satisfy the compiler, but if you then get a linker error, then the function is simply not included in the library in any case.
Related
Might be a stupid (and really simple) question, but I've wanted to try since I don't know where to find an answer for that. I'm realizing some book, and I've started googling something - I was actually kinda curious why, if we have files like these:
file1.c
#include <stdio.h>
#include "file2.h"
int main(void){
printf("%s:%s:%d \n", __FILE__, __FUNCTION__, __LINE__);
foo();
return 0;
}
file2.h
void foo(void);
and
file2.c
#include <stdio.h>
#include "file2.h"
void foo(void) {
printf("%s:%s:%d \n", __FILE__, __func__, __LINE__);
return;
}
compiling it with:
gcc file1.c file2.c -o file -Wall
Why is it a good practice to include the header file of file2.h which contains prototype of the foo function in the same file that foo is declared? I totally understand attaching it to file1.c, while we should use the header file to define the interface of each module, rather than writing it "raw", but why attaching header file with the prototype to the file where it is declared (file2.c)? -Wall option flag also does not say anything if I won't include it, so why people say it is "the correct way"? Does it help avoiding errors, or is it just for clearer code?
Those code samples are taken from this discussion:
Compiling multiple C files in a program
Where some user said it is 'the correct way'.
To answer this question, you should have a basic understanding of the difference between the compiler and the linker. In a nuttshell, the compiler, compilers each translation unit (C file) alone then it's the linker's job to link all the compiled files together.
For instance, In the above code the linker is the one who is searching where the function foo() called from main() exists and links to it.
The compiler step comes first then the linker.
Let's demonstrate an example where including file2.h in file2.c comes handy:
file2.h
void foo(void);
file2.c
#include <stdio.h>
#include "file2.h"
void foo(int i) {
printf("%s:%s:%d \n", __FILE__, __func__, __LINE__);
return;
}
Here the prototype of foo() is different from its definition.
By including file2.h in file2.c so the compiler can check whether the prototype of the function is equivalent to the definition of it, if not then you will get a compiler error.
What will happen if file2.h is not included in file2.c?
Then the compiler won't find any issue and we have to wait until the linking step when the linker will find that there is no matching for the function foo() called from main() and it will through an error.
Why bother then if the linker, later on, will find out the error anyway?
Because in big solutions there might be hundreds of source codes that take so much time to be compiled so waiting for the linker to raise the error at the end will waste a great amount of time.
This is The Only True ReasonTM:
If the compiler encounters a call of a function without a prototype, it derives one from the call, see standard chapter 6.5.2.2 paragraph 6. If that does not match the real function's interface, it's undefined behavior in most cases. At best it does no harm, but anything can happen.
Only with a high enough warning level, compilers emit diagnostics like warnings or errors. That's why you should always use the highest warning level possible, and include the header file in the implementation file. You will not want to miss this chance to let your code being checked automatically.
C doesn’t mangle symbols usually (there are some exceptions eg. on Windows). Mangled symbols would carry type information. Without it, the linker trusts that you didn’t make mistakes.
If you don’t include the header, you can declare the symbol to be one thing, but then define it to be whatever else. Eg. in the header you might declare foo to be a function, and then in the source file you can define it to be a totally incompatible function (different calling convention and signature), or even not a function at all – say a global variable. Such a project may link but won’t be functional. The error may be in fact hidden, so if you don’t have solid tests in place, you won’t catch it until a customer lets you know. Or worse, there’s a news article about it.
In C++ the symbol carries information about its type, so if you declare one thing and then define something with same base name but an incompatible type, the linker will refuse to link the project, since a particular symbol is referenced but never defined.
So, in C you include the header to prevent mistakes that the tools can’t catch, that will result in a broken binary. In C++, you do it so that you’ll get perhaps an error during compilation instead of later in the link phase.
Despite the fact that i included '#include ' to my code, when i use built-in qsort function, clang gives me the error:
schedule.o: In function `chooseTicket':
schedule.c:(.text+0x16d): undefined reference to `qsort'
clang: error: linker command failed with exit code 1 (use -v to see invocation)
start of the file (schedule.c) is like that:
#include "sched.h"
#include "schedproc.h"
#include <assert.h>
#include <minix/com.h>
#include <machine/archtypes.h>
#include <stdlib.h>
#include <lib.h>
#include <string.h>
#include <time.h>
and here is the function in which i used qsort built-in function
int chooseTicket(int* ticketList,int length,int totalTicket){
int randomValue;
int temp=0,prevTemp=0,selectedTicket=0,selectedIndex = 0;
time_t t;
struct schedproc *rmp;
int* sortedTicketList = malloc(length*sizeof(int));
memcpy(sortedTicketList,ticketList,length);
srandom((unsigned)time(&t));
randomValue = (random() % totalTicket);
qsort(sortedTicketList,length,sizeof(int),cmpFunc);//this line
note: Same errors also occured for 'rand()' and 'srand()' function and instead i have used 'random()' and 'srandom()', then the problem was solved. I don't understand despite the fact that 'rand()' and 'srand()' is generally accepted functions and header file contains these functions, why clang gives me linking errors while i am using 'rand()' and 'srand().
First, qsort is not a built-in, but part of the C standard library (formally, for hosted environments.)
Second, you need to learn that #include only allows access to the declarations of the functions in any given library. You need to link with the library, for your program to actually perform the call to the functionnality. Since you are getting a linker error here, no #include are going to help.
I guess you are writing a MINIX service, hence linking with libminc rather than with the full standard library ("libc"); in other words, this is a freestanding environment. And it happens qsort() is not in the restricted set of C functions included in libminc.
Either link with qsort.(c|o) specifically; or expand your own local version of libminc to include qsort(); or eat the whole cake and link with full libc, perhaps by adding DPADD+= ${LIBC}; LDADD+= -lc to the Makefile (I never tried to do that but it was supposed to work at some point, according to the code; it is not usual practice, so expect problems down the road.)
I am currently porting some OS related function of a software project from Linux to FreeBSD. Thereby, I recognized the following problem using getpagesize if _POSIX_C_SOURCE=200809Lis defined on FreeBSD 10.1.
I created a small test program
#include <stdio.h>
#include <unistd.h>
int main(int argc, char **argv)
{
int i = getpagesize();
return 0;
}
If I compile is using
cc test.c -o test
it compiles without any warnings. But if I define _POSIX_C_SOURCE=200809L (result of the proper POSIX definition of getline function which I need in other parts of the code) I get:
cc test.c -D_POSIX_C_SOURCE=200809L
test.c:5:10: warning: implicit declaration of function 'getpagesize' is invalid in C99 [-Wimplicit-function-declaration]
int i = getpagesize();
^
Although I included unistd.h as stated in the manpage of getpagesize. How can I make the code compiling without warnings with still defined _POSIX_C_SOURCE?
(1) The _POSIX_C_SOURCE is a wrong define. You need the _XOPEN_SOURCE. For example:
cc -D_XOPEN_SOURCE=700 test.c
or
cc -D_XOPEN_SOURCE=600 test.c
The 600 and 700 signify version of the Single Unix Specification (SUS for short, aka Open Group Specification, aka POSIX) your application expects from the system library. See here for the SUSv7.
(2) BUT. That might still not work, because the getpagesize() is a BSD-specific function, which actually might be hidden if you try to compile the file in the POSIX-compliance mode.
Normally you need nothing special to get access to the BSD functions on a BSD system, but portable way is to provide the _BSD_SOURCE define.
The more portable, POSIX-compliant way to get the page size is sysconf(_SC_PAGE_SIZE) function. FreeBSD man page.
P.S. Do not have a BSD at hand to test it.
I was able to run code that uses the randomize function without including the time.h library. is it automatically included with some other libraries i might have already included in my code? Below is a list of the libraries I included:
#include <graphics.h>
#include <stdlib.h>
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <string.h>
#include <io.h>
This is very very specific to the version and implementation of your library. The standard doesn't force any header to include time.h 1 so you cannot rely on that.
In your case, it could be that one of dos.h, io.h, conio.h for example has included time.h (or any other of the headers there for all it's worth).
1 At least not the ones there and not likely in your seemingly ancient library. C11 says threads.h should include time.h
What does <compiler with high warning level> yourcode.c say? My guess would be:
either one of the non-standard DOS-specific headers (conio.h, dos.h, io.h, ...) includes it,
or there's no declaration at all, i. e. it's not included, in which case your compiler silently and implicitly assumes a function signature (specifically, it assumes a return value of int and whatever type of argument you call it with for the first time).
Note that the latter case is wrong, and you should pay attention not to do it (since it may lead your program invoking undefined behavior). Always compile with all warnings enabled so you can track down such an error.
When C compiler can't find a prototype to a function it assumes it is a function that returns int. It also prints a warning function if you didn't change the default settings.
So. In your case perhaps time.h was included, but be aware that it can cause a lot of problems if it wasn't.
I'm pretty sure there's such question, but I can't find it :\ Anyway, here's the issue:
What is the difference between wait in stdlib.h and sys/wait.h o.O ?
In details - I just encountered this problem and I could't compile a simple C program. I isolated the problem and here's what I got:
#include <stdlib.h>
//#include <sys/wait.h>
int main()
{
int status;
wait( &status );
return 0;
}
If stdlib.h is included, I got:
$ gcc asd.cpp
asd.cpp: In function ‘int main()’:
asd.cpp:9:16: error: conflicting declaration ‘wait& status’
asd.cpp:8:6: error: ‘status’ has a previous declaration as ‘int status’
What declaration ? O.o What is wait here, that conflicts with int status?
I found a thread in the net, where replacing stdlib.h with sys/wait.h solves the problem, but why is that and what is the difference?
EDIT: Thanks to sidyll's comment, I changed the file extention - from .cpp to .c and it worked! I'm shocked :) How is this so different? And still the same question - what is the different between those two wait-s ?
The difference is that the wait() in <sys/wait.h> is the one you should use.
From the wait(3) man page:
SYNOPSIS
#include <sys/types.h>
#include <sys/wait.h>
pid_t wait(int *status);
The wait function isn't defined by the ISO C standard, so a conforming C implementation isn't allowed to declare it in <stdlib.h> (because it's legal for a program to use the name wait for its own purposes). gcc with glibc apparently does so in its default non-conforming mode, but if you invoke it with gcc -ansi -pedantic or gcc -std=c99 -pedantic, it doesn't recognize the function name wait or the type pid_t.
I did gcc -E wait.cpp to dump the actual preprocessor expansions that take place. What I found was that on linux, the header /usr/include/bits/waitstatus.h is included which pulls in a union wait { ... } but the function wait() from sys/wait.h is never pulled in. The same thing happens with the c compilation, but the for whatever reason the compiler does not complain in that case.
To prove this to yourself, you can change your main to declare the wait as a variable rather than a function call, and the compiler will not complain:
int main() {
int status;
wait w;
return 0;
}
Note that GCC stands for GNU Compiler Collection, not GNU C Compiler (as many
other tools which were prefixed with a g). It's not a C-only compiler. And
many languages are detected by file extensions. Adam Rosenfield is partialy
correct in his comment. Yes, g++ will add the C++ library in the linker phase,
but that's not the unique difference (more on this later).
To explain how changing the extension solved it, please take a look in this text
straight from GCC's manual:
Compiling C++ Programs
C++ source files conventionally use one of the suffixes.C, .cc, .cpp,
.CPP, .c++, .cp,or.cxx;C++ header files often use.hhor.H;and
preprocessed C++ files use the suffix .ii. GCC recognizes files with
these names and compiles them as C++ programs even if you call the
compiler the same way as for compiling C programs (usually with the
namegcc).
So, "GCC regocnizes files with these names" and your program was being compiled
as C++ source. I guess that C++ has some special use of &, which I can't tell
exactly (I don't know C++). Hence the error.
Now, regarding the difference between g++ and gcc, continue with the next
paragraph:
However, the use ofgccdoes not add the C++ library.g++is a program
that calls GCC and treats.c, .hand.ifiles as C++ source files
instead of C source files unless-xis used, and automatically
specifies linking against the C++ library. This program is also useful
when precompiling a C header file with a.hextension for use in C++
compilations. On many systems,g++is also installed with the name
c++.
On the real question: there aren't two waits here in my system (Darwin 11), only
the standard syscall. Check if what Kevin said isn't happening. It's the same,
stdlib.h includes sys/wait.h:
#include <_types.h>
#if !defined(_ANSI_SOURCE)
#include <sys/wait.h>
#if (!defined(_POSIX_C_SOURCE) || defined(_DARWIN_C_SOURCE))
#include <alloca.h>
#endif /* (!_POSIX_C_SOURCE || _DARWIN_C_SOURCE) */
#endif /* !_ANSI_SOURCE */
Check your header.