File: autoconf.info, Node: Function Portability, Next: Particular Functions, Up: Library Functions 5.5.1 Portability of C Functions -------------------------------- Most usual functions can either be missing, or be buggy, or be limited on some architectures. This section tries to make an inventory of these portability issues. By definition, this list always requires additions. A much more complete list is maintained by the Gnulib project (*note Gnulib::), covering *note Current POSIX Functions: (gnulib)Function Substitutes, *note Legacy Functions: (gnulib)Legacy Function Substitutes, and *note Glibc Functions: (gnulib)Glibc Function Substitutes. Please help us keep the Gnulib list as complete as possible. ‘exit’ On ancient hosts, ‘exit’ returned ‘int’. This is because ‘exit’ predates ‘void’, and there was a long tradition of it returning ‘int’. On current hosts, the problem more likely is that ‘exit’ is not declared, due to C++ problems of some sort or another. For this reason we suggest that test programs not invoke ‘exit’, but return from ‘main’ instead. ‘malloc’ The C standard says a successful call ‘malloc (0)’ is implementation dependent. It can return either ‘NULL’ or a new non-null pointer. The latter is more common (e.g., the GNU C Library) but is by no means universal. ‘AC_FUNC_MALLOC’ can be used to insist on non-‘NULL’ (*note Particular Functions::). ‘putenv’ POSIX prefers ‘setenv’ to ‘putenv’; among other things, ‘putenv’ is not required of all POSIX implementations, but ‘setenv’ is. POSIX specifies that ‘putenv’ puts the given string directly in ‘environ’, but some systems make a copy of it instead (e.g., glibc 2.0, or BSD). And when a copy is made, ‘unsetenv’ might not free it, causing a memory leak (e.g., FreeBSD 4). On some systems ‘putenv ("FOO")’ removes ‘FOO’ from the environment, but this is not standard usage and it dumps core on some systems (e.g., AIX). On MinGW, a call ‘putenv ("FOO=")’ removes ‘FOO’ from the environment, rather than inserting it with an empty value. ‘realloc’ It is problematic to call ‘realloc’ with a zero size. The C standard says ‘realloc (NULL, 0)’ is equivalent to ‘malloc (0)’, which means one cannot portably tell whether the call has succeeded if it returns a null pointer. If ‘ptr’ is non-null, the C standard says ‘realloc (ptr, 0)’ has undefined behavior. The ‘AC_FUNC_REALLOC’ macro avoids some of these portability issues. *Note Particular Functions::. ‘signal’ handler In most cases, it is more robust to use ‘sigaction’ when it is available, rather than ‘signal’. ‘snprintf’ In C99 and later, if the output array isn’t big enough and if no other errors occur, ‘snprintf’ and ‘vsnprintf’ truncate the output and return the number of bytes that ought to have been produced. Some older systems, notably Microsoft Windows before Visual Studio 2015 and Windows 10, do not null-terminate the output and return −1 instead. Portable code can check the return value of ‘snprintf (buf, sizeof buf, ...)’: if the value is negative or is not less than ‘sizeof buf’, an error occurred and the contents of ‘buf’ can be ignored. Alternatively, one of the Gnulib modules related to ‘snprintf’ can be used. *Note Gnulib::. ‘strerror_r’ POSIX specifies that ‘strerror_r’ returns an ‘int’, but many systems (e.g., the GNU C Library) provide a different version returning a ‘char *’. ‘AC_FUNC_STRERROR_R’ can detect which is in use (*note Particular Functions::). ‘strnlen’ Android 5.0’s strnlen was broken, because it assumed the addressed array always had at least the specified number of bytes. For example, ‘strnlen ("", SIZE_MAX)’ should return 0 but on Android 5.0 it crashed. AIX 4.3 provided a broken version which produces the following results: strnlen ("foobar", 0) = 0 strnlen ("foobar", 1) = 3 strnlen ("foobar", 2) = 2 strnlen ("foobar", 3) = 1 strnlen ("foobar", 4) = 0 strnlen ("foobar", 5) = 6 strnlen ("foobar", 6) = 6 strnlen ("foobar", 7) = 6 strnlen ("foobar", 8) = 6 strnlen ("foobar", 9) = 6 ‘sysconf’ ‘_SC_PAGESIZE’ is standard, but some older systems (e.g., HP-UX 9) have ‘_SC_PAGE_SIZE’ instead. This can be tested with ‘#ifdef’. ‘unlink’ The POSIX spec says that ‘unlink’ causes the given file to be removed only after there are no more open file handles for it. Some non-POSIX hosts have trouble with this requirement, though, and some DOS variants even corrupt the file system. ‘unsetenv’ On MinGW, ‘unsetenv’ is not available, but a variable ‘FOO’ can be removed with a call ‘putenv ("FOO=")’, as described under ‘putenv’ above. ‘va_copy’ C99 and later provide ‘va_copy’ for copying ‘va_list’ variables. It may be available in older environments too, though possibly as ‘__va_copy’ (e.g., ‘gcc’ in strict pre-C99 mode). These can be tested with ‘#ifdef’. A fallback to ‘memcpy (&dst, &src, sizeof (va_list))’ gives maximum portability. ‘va_list’ ‘va_list’ is not necessarily just a pointer. It can be a ‘struct’, which means ‘NULL’ is not portable. Or it can be an array, which means as a function parameter it can be effectively call-by-reference and library routines might modify the value back in the caller. Signed ‘>>’ Normally the C ‘>>’ right shift of a signed type replicates the high bit, giving a so-called “arithmetic” shift. But care should be taken since Standard C doesn’t require that behavior. On a few platforms (e.g., Cray C by default) zero bits are shifted in, the same as a shift of an unsigned type. Integer ‘/’ C divides signed integers by truncating their quotient toward zero, yielding the same result as Fortran. However, before C99 the standard allowed C implementations to take the floor or ceiling of the quotient in some cases. Hardly any implementations took advantage of this freedom, though, and it’s probably not worth worrying about this issue nowadays.
