I am trying to make a C program that uses named pipes to communicate with a C++ program on a Raspberry Pi 3.
The warning that GCC is spitting out when I compile some code of mine:
/home/pi/BluetoothTest/btooth.c|76|warning: implicit declaration of function ‘mknod’ [-Wimplicit-function-declaration]|
Here is the code from for the function, including the #if above it:
#if defined __USE_MISC || defined __USE_BSD || defined __USE_XOPEN_EXTENDED
extern int mknod (const char *__path, __mode_t __mode, __dev_t __dev)
__THROW __nonnull ((1));
and here are the includes that I have in the file:
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/hci.h>
#include <bluetooth/hci_lib.h>
#include <bluetooth/rfcomm.h>
//#include <linux/stat.h>
The program attempts to create the pipe here:
umask(0);
fifo = mknod(PIPE_LOC, S_IFIFO|0666, 0);
fp = fopen(PIPE_LOC, "w");
fifo is an int that isn't used anywhere else and fp is a FILE* to the pipe. Some debugging that I have done shows that fifo has a value of -1 after mknod runs, likely because of the compiler not seeming to be able to find the implementation of the function.
How do I make it so that GCC knows where to find the implementation of mknod?
As you can see that for declaration of mknod() function to stay after preprocessing stage, one of three macros (__USE_MISC, __USE_BSD, __USE_XOPEN_EXTENDED) should be defined. Otherwise, declaration of mknod() will be removed during preprocessing stage.
#if defined __USE_MISC || defined __USE_BSD || defined __USE_XOPEN_EXTENDED
extern int mknod (const char *__path, __mode_t __mode, __dev_t __dev)
__THROW __nonnull ((1));
You can use compiler options: -std=gnu99 -D_GNU_SOURCE or you can define these macros on your own and place them above header file inclusion.
I think you're missing a definition of some feature test macro required for the respective headers to define mknod. According to the Linux Programmer's Manual for the function (man 2 mknod) the macros for glibc are:
mknod():
_XOPEN_SOURCE >= 500
|| /* Since glibc 2.19: */ _DEFAULT_SOURCE
|| /* Glibc versions <= 2.19: */ _BSD_SOURCE || _SVID_SOURCE
Try adding -D_XOPEN_SOURCE=500 to your compile flags to see if that helps.
Related
I don't understand why the function getpagesize gives me a warning for implicit declaration of function while using the c18 version of gcc.
gcc test.c -Wall -std=c18
implicit declaration of function ‘getpagesize’ [-Wimplicit-function-declaration]
nested extern declaration of ‘getpagesize’ [-Wnested-externs]
int BLOCKSIZE = getpagesize();
And this is my included files :
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/resource.h>
#include <stdint.h>
#include <errno.h>
Using -std=cXX instead of -std=gnuXX disables a bunch of normally defined feature test macros, including the ones that provide getpagesize(). From its man page (Assuming you're using linux):
Feature Test Macro Requirements for glibc (see feature_test_macros(7)):
getpagesize():
Since glibc 2.19:
_DEFAULT_SOURCE || ! (_POSIX_C_SOURCE >= 200112L)
From glibc 2.12 to 2.19:
_BSD_SOURCE || ! (_POSIX_C_SOURCE >= 200112L)
Before glibc 2.12:
_BSD_SOURCE || _XOPEN_SOURCE >= 500
So you have to define the appropriate one to the appropriate value before including any header files. Or just use -std=gnu18.
Edit: Also, since getpagesize() is obsolete and not standard, consider using the POSIX standard sysconf(_SC_PAGESIZE) instead.
In the following code, it is compiled success and print 1024
#include <stdio.h>
#define FD_SETSIZE 512
#include <sys/types.h>
int main()
{
printf("%d\n", FD_SETSIZE);
}
But in the following code, it is compiled failed and print
test.c:4:1: warning: "FD_SETSIZE" redefined
In file included from /usr/include/sys/types.h:220,
from test_fd.c:3:
/usr/include/sys/select.h:81:1: warning: this is the location of the previous definition
the code is
#include <stdio.h>
#include <sys/types.h>
#define FD_SETSIZE 512
int main()
{
printf("%d\n", FD_SETSIZE);
}
Can anbody explain this? Thanks!
But in the following code, it is compiled failed and print
In the question, both the programs were compiled, but while compiling first program you got warnings in preprocessor stage.
Preprocessor stage is responsible for the replacement of macros.
In this example the preprocessor is using the last defined macro and replacing it.
#include <stdio.h>
#define FD_SETSIZE 512
#include <sys/types.h>
Here the definition of FD_SETSIZE is there in both the .c file and also in header file sys/types.h.
After the file inclusion, then the replacing of macros will be done,so the latest defined macro is replaced.
So the final replacement FD_SETSIZE of will be same as defined in the sys/types.h file and vice-versa.
Hope this is helpful.
you can use the #undef directive to remove the defined macro and replace it later
#ifdef MACRO
#undef MACRO
#endif
#define MACRO
I don't know why it still says HOST_NAME_MAX is implicit declaration.
Instead, I searched the web and do the following to fix it:
#include <netdb.h>
and use MAXHOSTNAMELEN instead of HOST_NAME_MAX
however, I am not very sure it this is a good way, and the reasons behind it.
Using grep:
$ grep -rl '#define HOST_NAME_MAX' /usr/include
We can see that HOST_NAME_MAX is defined in:
/usr/include/bits/local_lim.h
And local_lim.h is included by /usr/include/bits/posix1_lim.h:
# grep -rl local_lim.h /usr/include
/usr/include/bits/posix1_lim.h
And posix1_lim.h is included by limits.h only if __USE_POSIX is defined:
#ifdef __USE_POSIX
/* POSIX adds things to <limits.h>. */
# include <bits/posix1_lim.h>
#endif
So if your code looks like:
#define __USE_POSIX
#include <limits.h>
You should have the HOST_NAME_MAX constant available. Having said that, on my system __USE_POSIX appears to be defined by default. For example, the following code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>
int main(int argc, char **argv) {
#ifdef __USE_POSIX
printf("__USE_POSIX is defined\n");
#endif
printf("HOST_NAME_MAX: %d\n", HOST_NAME_MAX);
return 0;
}
Prints:
__USE_POSIX is defined
HOST_NAME_MAX: 64
I have three files, say A.c , B.c and C.c, all of which #include common.h
In common.h, I include "sys/socket.h" and I protect the common.h by macros:
#ifndef __COMMON_H
#define __COMMON_H
// body of file goes here
#endif
When i compile the code, I get several errors such as below
In file included from /usr/include/sys/socket.h:40,
from tcpperf.h:4,
from wrapunix.c:1:
/usr/include/bits/socket.h:425: error: conflicting types for 'recvmmsg'
/usr/include/bits/socket.h:425: note: previous declaration of 'recvmmsg' was here
In file included from /usr/include/sys/socket.h:40,
from tcpperf.h:4,
from wrapsock.c:1:
As you can see wrapunix.c and wrapsock.c, they both include tcpperf.h, but tcpperf.h is guarded with macros,yet gcc complains that recvmsg was declared multiple times. How do I resolve this issue?
Update:
Here is the header of tcpperf.h, that is causing issues
#ifndef _TCPPERF_H
#define _TCPPERF_H
#include <sys/types.h>
#include <sys/socket.h>
#include <time.h>
#include <regex.h>
#include <errno.h>
#include <sched.h>
#include <pthread.h>
#include <argp.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <linux/tcp.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <sys/prctl.h>
#include <unistd.h>
#include <sys/wait.h>
#endif
The above error can be reproduced by providing "-combine -fwhole-program" flags to gcc such as
gcc -std=gnu99 -Wall -combine -fwhole-program -I. error.c wrapunix.c wrapsock.c file1.c file2.c -o file2 -lrt
The error is "conflicting types for 'recvmmsg'" rather than just duplicate definition (which would be tolerated if equal). That means your .c source receives two different version of recvmmsg: one by your direct tcpperf.h inclusion and another one by inclusion it via sys/socket.h. I believe you have another version of tcpperf.h elsewhere in inclusion path with different (perhaps older version) recvmmsg.
The problem is almost certainly related to -combine. This is a bit of a guess, but in looking at the definition of recvmmsg:
extern int recvmmsg (int __fd, struct mmsghdr *__vmessages,
unsigned int __vlen, int __flags,
__const struct timespec *__tmo);
note that it takes a struct mmsghdr as an argument. However, while this prototype is unconditional, struct mmsghdr is only defined if __USE_GNU is set:
#ifdef __USE_GNU
/* For `recvmmsg'. */
struct mmsghdr
{
struct msghdr msg_hdr; /* Actual message header. */
unsigned int msg_len; /* Number of received bytes for the entry. */
};
#endif
-combine is basically equivalent to concatenating all your files together and then compiling them. Is there any chance that between the text of wrapunix.c and wrapsock.c that GNU_SOURCE is being defined? If that happened, then the first definition of recvmmsg would use a definition of struct mmsghdr that was local to just the prototype, while the second definition would use the real struct. Those two definitions would then be incompatible, which would result in the error message that you got.
I have a function, createFile that uses fchmod:
int createFile(char *pFileName) {
int ret;
if ((ret = open(pFileName, O_RDWR | O_CREAT | O_TRUNC)) < 0)
errorAndQuit(2);
fchmod(ret, S_IRUSR | S_IWUSR);
return ret;
}
At the top of my file, I have the following includes:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <fcntl.h>
When compiling: the compiler spits out:
warning: implicit declaration of function ‘fchmod’
I'm including all of the correct files, yet getting this warning. The program runs fine, even with the warning.
By a happy coincidence, your question is directly answered by the feature_test_macros(7) manpage:
Specification of feature test macro requirements in manual pages
When a function requires that a feature test macro is
defined, the manual page SYNOPSIS typically includes a note
of the following form (this example from the chmod(2) manual
page):
#include <sys/stat.h>
int chmod(const char *path, mode_t mode);
int fchmod(int fd, mode_t mode);
Feature Test Macro Requirements for glibc (see
feature_test_macros(7)):
fchmod(): _BSD_SOURCE || _XOPEN_SOURCE >= 500
The || means that in order to obtain the declaration of
fchmod(2) from <sys/stat.h>, either of the following macro
definitions must be made before including any header files:
#define _BSD_SOURCE
#define _XOPEN_SOURCE 500 /* or any value > 500 */
Alternatively, equivalent definitions can be included in the
compilation command:
cc -D_BSD_SOURCE
cc -D_XOPEN_SOURCE=500 # Or any value > 500
You didn't specify what compiler or platform you're using, but on my recent Linux installation, fchmod() is defined in but guarded by a couple of #ifdefs (__USD_BSD and __USE_XOPEN_EXTENDED).
You aren't supposed to set those directly, but rather via the _FOO_SOURCE macros in . Try defining _XOPEN_SOURCE_EXTENDED or just _GNU_SOURCE and recompiling (and note that these macros enable nonstandard functionality and use of the functionality they enable may limit the portability of your code).
I have faced this error while building uml.
Just add this line in the file where this error is thrown:
#include "sys/stat.h"
I believe it will take care about adding the macros defined in the above answers.