Implicit declaration of function 'getaddrinfo' on MinGW - c

I have a C program that uses getaddrinfo(). It works as expected on Linux and Mac OS X.
I'm in the middle of porting it to Windows.
When I compile it (with MinGW gcc) I get the following warnings:
ext/socket/socket.c: In function 'sl_tcp_socket_init':
ext/socket/socket.c:98:5: warning implicit declaration of function 'getaddrinfo' [-Wimplicit-function-declaration]
ext/socket/socket.c:104:9: warning implicit declaration of function 'freeaddrinfo' [-Wimplicit-function-declaration]
Then the entire thing fails to link with undefined references to getaddrinfo() and freeaddrinfo().
Now, according to this MSDN page, getaddrinfo() is supported on Windows and is located in the header file Ws2tcpip.h and the library file Ws2_32.lib.
I'm including Ws2tcpip.h and linking with -lWs2_32, so I'm not sure why this isn't working.

If you have a look at line 297 of ws2tcpip.h, you can see that there's a check of the value of _WIN32_WINNT.
#if (_WIN32_WINNT >= 0x0501)
void WSAAPI freeaddrinfo (struct addrinfo*);
int WSAAPI getaddrinfo (const char*,const char*,const struct addrinfo*,
struct addrinfo**);
int WSAAPI getnameinfo(const struct sockaddr*,socklen_t,char*,DWORD,
char*,DWORD,int);
#else
/* FIXME: Need WS protocol-independent API helpers. */
#endif
Just #define _WIN32_WINNT before your includes.

If you want to make your code compiler-wide you should actually also define NTDDI_VERSION with the same OS version as _WIN32_WINNT. Without that defining only _WIN32_WINNT will not let you to use getaddrinfo() with some compilers (i.e. Watcom). It is better to wrap it in the same way as Windows SDK does:
#define _NTDDI_VERSION_FROM_WIN32_WINNT2(ver) ver##0000
#define _NTDDI_VERSION_FROM_WIN32_WINNT(ver) _NTDDI_VERSION_FROM_WIN32_WINNT2(ver)
#ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x501
#endif
#ifndef NTDDI_VERSION
# define NTDDI_VERSION _NTDDI_VERSION_FROM_WIN32_WINNT(_WIN32_WINNT)
#endif

Supposedly the proper way to fix this is:
#define WINVER WindowsXP
Or perhaps more sensibly adding -DWINVER=WindowsXP to your CPPFLAGS.
Ref: http://mingw.5.n7.nabble.com/Undefined-reference-to-getaddrinfo-td5694.html
Note: didn’t work for me however.

Related

VSCode C/C++ Intellisense issue with netinet/ip.h

VSCode reports an incomplete type is not allowed error when trying to use struct ip.
I know this is a problem with intellisense as my program compiles just fine using gcc monitor.c -o monitor -lnet so there isn't an actual error, but intellisense seems to disagree.
Here is the minimal code to get the error:
#include <netinet/ip.h>
#include <stdlib.h>
int main()
{
struct ip * my_ip = (struct ip *) malloc(sizeof(struct ip));
}
I tried adding /usr/include/** to the c_cpp_propertied.json file.
Taking a look into the ip.h file directly I can see that the struct definition is "hidden" inside an #ifdef __USE_MISC so I added that to the defines section of c_cpp_propertied.json with no luck.
I'm fresh out of ideas and I haven't been able to find anything related to the issue. Nothing helpful anyway.
Taking a look into the ip.h file directly I can see that the struct definition is "hidden" inside an #ifdef __USE_MISC so I added that to the defines section of c_cpp_propertied.json with no luck.
According to this you can try to do following in your example:
#ifndef __USE_MISC
#define __USE_MISC
#endif // __USE_MISC
#include <netinet/ip.h>
#include <stdlib.h>
int main()
{
struct ip * my_ip = (struct ip *) malloc(sizeof(struct ip));
}
Explanation: You mentioned that struct is hidden in #ifdef __USE_MISC preprocessor condition. Which means it's only visible if somewhere in your code before this file the definition #define __USE_MISC exists, or if this definiton is passed via compiler flags. Seems like VSCode C/C++ Intellisense isn't doing this, while gcc does
P.S. Also, please take a look at what does this macro means and what does it used for: link
P.P.S. After further investigation was found that OP has no _DEFAULT_SOURCE definition defined in his compiler flags/source files.
So, the actual answer is to add following snippet of code before includes (or to the compiler flags or IDE settings):
#ifndef _DEFAULT_SOURCE
#define _DEFAULT_SOURCE
#endif // _DEFAULT_SOURCE
#include <netinet/ip.h>
// ...

Why only define a macro if it's not already defined?

All across our C code base, I see every macro defined the following way:
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
#ifndef BEEPTRIM_ROLL_RATE_DEGPS
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#endif
#ifndef FORCETRIMRELEASE_HOLD_TIME_MS
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#endif
#ifndef TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
#endif
What is the rationale of doing these define checks instead of just defining the macros?
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#define BEEPTRIM_ROLL_RATE_DEGPS 0.2f
#define FORCETRIMRELEASE_HOLD_TIME_MS 1000.0f
#define TRIMSYSTEM_SHEARPIN_BREAKINGFORCE_LBS 50.0f
I can't find this practice explained anywhere on the web.
This allows you to override the macros when you're compiling:
gcc -DMACRONAME=value
The definitions in the header file are used as defaults.
As I said in the comment, imagine this situation:
foo.h
#define FOO 4
defs.h
#ifndef FOO
#define FOO 6
#endif
#ifndef BAR
#define BAR 4
#endif
bar.c
#include "foo.h"
#include "defs.h"
#include <stdio.h>
int main(void)
{
printf("%d%d", FOO, BAR);
return 0;
}
Will print 44.
However, if the conditional ifndef was not there, the result would be compilation warnings of MACRO redefinition and it will print 64.
$ gcc -o bar bar.c
In file included from bar.c:2:0:
defs.h:1:0: warning: "FOO" redefined [enabled by default]
#define FOO 6
^
In file included from bar.c:1:0:
foo.h:1:0: note: this is the location of the previous definition
#define FOO 4
^
I do not know the context but this can be used to give the user the availability to override the values set by those macro definitions. If the user explicitly defines a different value for any of those macros it will be used instead of the values used here.
For instance in g++ you can use the -D flag during compilation to pass a value to a macro.
This is done so that the user of the header file can override the definitions from his/her code or from compiler's -D flag.
Any C project resides on multiple source files. When working on a single source file the checks seem to (and actually) have no point, but when working on a large C project, it's a good practice to check for existing defines before defining a constant. The idea is simple: you need the constant in that specific source file, but it may have been already defined in another.
You could think about a framework/library that gives to the user a default preset that allow the user to compile and work on it.
Those defines are spreaded in different files and the final user is advised to include it's config.h file where he can config its values.
If the user forgot some define the system can continue to work because of the preset.
Using
#ifndef BEEPTRIM_PITCH_RATE_DEGPS
#define BEEPTRIM_PITCH_RATE_DEGPS 0.2f
#endif
allows the user to define the value of the macro using the command line argument (in gcc/clang/VS) -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f.
There is another important reason. It is an error to re-define a preprocessor macro differently. See this answer to another SO question. Without the #ifndef check, the compiler should produce an error if -DBEEPTRIM_PITCH_RATE_DEGPS=0.3f is used as a command line argument in the compiler invocation.

C program compiler warning only in Windows (MinGW-w64)

I built a multi-language software image processing program and made it generally available with binaries for Mac OS X and Ubuntu. The binaries have been tested on their respective operating systems and every thing works perfectly. I recently also tried to release binaries for Windows (64 bit) but the GCC (through MinGW-w64) compiler gave me warnings for one of the C programs when I create the shared library (dll) file. This did not happen in Mac OS X or Ubuntu. Here are the warnings and the corresponding line of code in the C file:
warning: passing argument 3 of '_beginthreadex' from incompatible pointer type [enabled by default]
Line 464:
ThreadList[i] = (HANDLE)_beginthreadex( NULL, 0, &ThreadFunc, &ThreadArgs[i] , 0, NULL );
The second and stranger warning:
c:\mingw\x86_64-w64-mingw32\include\process.h:31:29: note:
expected 'unsigned int <*><void *>' but argument is of type 'void * <*><void *>'
_CRTIMP uintptr_t _cdecl _beginthreadex<void *_Security,unsigned _Stacksize,unsigned <_stdcall *_StartAddress> <void *>,void *_ArgList,unsigned _InitFlag,unsigned *_ThrdAddr >;
Line 34:
#include <process.h>
This belongs in this larger code block:
/* Multithreading stuff*/
#ifdef _WIN32
#include <windows.h>
#include <process.h>
#else
#include <pthread.h>
#endif
#include <stdbool.h>
The problem seems to emanate from #include <process.h> since for Mac OS X and Ubuntu #include <pthread.h> is used. Any help figuring this out? The full C program is here .
The messages when compiling for windows but not for other systems are hardly surprising. The offending code will only be seen by the compiler when building for windows, due to usage of the _WIN32 macro which is only defined by the compiler when code is built for windows.
The "second and stranger warning" is describing the cause. The third argument of the (windows specific) _beginthreadex() function is specified to be a pointer to a function that returns an unsigned int. The actual ThreadFunc being passed is a function that returns a void *.
The fix to make the code acceptable to a windows compiler is to change the return type of ThreadFunc() to return unsigned int. That will break the code for other systems, so you need to do the changes conditionally (i.e. have two versions of the function, and select the right one by testing the _WIN32 macro).
#ifdef _WIN32
/* use the windows version of the function here */
#else
/* use the non-windows version of the function here */
#endif

be64toh not linking or being declared when compiling with -std=c99

When I compile the following program (the code for all the defines I've gotten from 64 bit ntohl() in C++? which seemed sensible):
#include <stdint.h>
#if defined(__linux__)
#include <endian.h> //htobe64,be64toh
#include <arpa/inet.h> //ntohs, ntohl, htonl, htons
#elif defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/endian.h>
#elif defined(__OpenBSD__)
#include <sys/types.h>
#define be16toh(x) betoh16(x)
#define be32toh(x) betoh32(x)
#define be64toh(x) betoh64(x)
#endif
int main()
{
int64_t i = 0x1212121234343434;
int64_t j = be64toh(i);
return 0;
}
I get a linking error when compiling it with the following command (I'm running linux):
gcc -std=c99 endian_test.c -o endian
The error i receive is:
user#host ~/src/c $ gcc -std=c99 derp.c
endian_test.c: In function ‘main’:
endian_test.c:17:2: warning: implicit declaration of function ‘be64toh’ [-Wimplicit-function-declaration]
int64_t j = be64toh(i);
^
/tmp/ccYonfH4.o: In function `main':
endian_test.c:(.text+0x23): undefined reference to `be64toh'
collect2: error: ld returned 1 exit status
Which to me indicates two things, the header itself is included but doesn't really contain the functions/macros needed for this to work and because that means the compiler hopes it's gonna find the function later it tries to go ahead anyway but fails when trying to link.
But if i use the following command to compile (just remove -std=c99):
gcc endian_test.c -o endian
Everything is smooth as butter and works. Any idea why it's happening and what i could do to remedy it? To me it doesn't make sense that functions given by the kernel (or am i mistaken in that fact?) change depending on what standard i use when compiling?
Thanks in advance!
Without explicit -std= option, calling gcc is the same as -std=gnu89 with means C89 + GNU extensions. The GNU extensions will enable macros which will enable the presence of the functions in your header.
If you see the be64toh manual, you will see that it needs the _BSD_SOURCE to be defined. So on Linux #define it before you include <endian.h>.
I had this problem. The solution was to declare not only
#define _BSD_SOURCE
but also
#define __USE_BSD
https://github.com/tailhook/zerogw/pull/34/files#r32008569
Recent changes to glibc has meant you need
#define _DEFAULT_SOURCE
instead of
#define _BSD_SOURCE
Deprecation of _BSD_SOURCE and _SVID_SOURCE feature macros

Why is _GNU_SOURCE macro required for pthread_mutexattr_settype() while it is in POSIX/IEEE standard?

I have written a multithread server program in C, which echoes back all the data that a client sends.
Initially, I used poll() function in my program to detect POLLRDHUP event, for that I defined _GNU_SOURCE macro (This event is defined here).
Later I updated my code & removed poll() function, however I forgot to remove _GNU_SOURCE macro.
Now my code is finally complete (and a little long to post, more than 250 lines). Before removing macro I was compiling my program using:
gcc multi_thread_socket_v4.c -Wall -Werror -g -lpthread -o multi_thread_socket
and it worked fine: No errors, no warnings
After I removed the macro definition, and compiled using same command-line, the output of gcc was:
multi_thread_socket_v4.c: In function ‘main’:
multi_thread_socket_v4.c:194: warning: implicit declaration of function ‘pthread_mutexattr_settype’
multi_thread_socket_v4.c:194: error: ‘PTHREAD_MUTEX_ERRORCHECK’ undeclared (first use in this function)
multi_thread_socket_v4.c:194: error: (Each undeclared identifier is reported only once
multi_thread_socket_v4.c:194: error: for each function it appears in.)
I have included all the required libraries as it worked fine initially.
I peeked into pthread.h at /usr/include/pthread.h and found out this:
/* Mutex types. */
enum
{
PTHREAD_MUTEX_TIMED_NP,
PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_ADAPTIVE_NP
#ifdef __USE_UNIX98
,
PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,
PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
#endif
#ifdef __USE_GNU
/* For compatibility. */
, PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP
#endif
};
and this:
#ifdef __USE_UNIX98
/* Return in *KIND the mutex kind attribute in *ATTR. */
extern int pthread_mutexattr_gettype (__const pthread_mutexattr_t *__restrict
__attr, int *__restrict __kind)
__THROW __nonnull ((1, 2));
/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
PTHREAD_MUTEX_DEFAULT). */
extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
__THROW __nonnull ((1));
I checked out here to check if __USE_UNIX98 is a feature test macro, but it was not there.
So please help me understanding the reasons for the error, because the function & the macro where gcc shows error are defined in POSIX standard. I do not know what more info regarding my problem will be required so please tell me, I will update my question.
You should use
#define _POSIX_C_SOURCE 200112L
if you want to use POSIX features such as pthread_mutexattr_settype ... see http://pubs.opengroup.org/onlinepubs/007904975/functions/xsh_chap02_02.html
Another possibility is
#define _XOPEN_SOURCE 700
See http://man7.org/linux/man-pages/man7/feature_test_macros.7.html and http://pubs.opengroup.org/onlinepubs/9699919799/
Setting _GNU_SOURCE includes POSIX and lots of other definitions.
P.S. I would expect that including <pthread.h> includes <features.h>, which by default defines _POSIX_C_SOURCE as 200112L, but it's possible that you have defined something that overrides that ... see /usr/include/features.h on your system for details of the symbols and their usage.
It doesn't, your problem likely lies elsewhere.
I just compiled a trivial program with the following content:
#include <pthread.h>
int main(int argc, char **argv)
{
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_ERRORCHECK);
return 0;
}
This compiles perfectly with gcc -pthread -Wall -Werror a.c.
It's possible that another part of your program causes this, by eg. doing something silly like defining _PTHREAD_H, or some other minor sabotage.
You might want to try to get a minimal test case by using a tool like delta or creduce, which will probably make the problem evident.
When you're using old libraries (e.g. 2.1.x) you should use
#define __USE_UNIX98
Using a macro beginning with "__" it's not usually a good idea, but sometimes it's the only way... see also this discussion

Resources