portable c

http://daniel.haxx.se/projects/portability/


C Source Code Portability

Functions (limited to libc and "system" ones), general often-used concepts andvariable types. Include known flaws, work-arounds, autoconf tests and generalcomments from past experiences.

If you find flaws or have additional data to offer, please mail me. My emailaddress is visible at the bottom of the page. This page is destined to alwaysbe "under construction".

Related useful resources: predef.sf.net, Unix IncompatibilityNotes, Tips ForWriting Portable C

Functions

FunctionIssues
basenameFreeBSD 3.4 does not include the standard function basename().
bcopyOld-style BSD function, use memcpy() for portability
bzeroOld-style BSD function, use memset() for portability
gettimeofdayNot available on Windows, otherwise widely available. clock_gettime() is a newer POSIX/TSUSv2 function with higher resolution.
getaddrinfoOnly available in recent modern operating systems(gethostbyname() must be used on the others). NI_WITHSCOPEID (not present inmingw, glibc 2.3.2, Tru64 5.1, IRIX 6.5.22) and AI_NUMERICHOST (not present inAIX 4.3) are not universally available even if the getaddrinfo() function ispresent

Using the PF_UNSPEC option on Linux hosts that are ipv6-enabledbut that doesn't have the ipv6 kernel module loaded cause very slow nameresolves. This is usually worked around by first trying if a ipv6 socket canbe made and if not, no ipv6 resolves are attempted (PF_INET).

gethostbyaddr_rNot needed on Windows, HP-UX 11 and AIX 5(since gethostbyaddr() is then thread-safe on its own). Not existant on olderplatforms. Three different APIs:

5 arg version: int gethostbyaddr_r(char *address, intlength, int type, struct hostent *he, struct hostent_data *data)

7 arg version: struct hostent *gethostbyaddr_r(char*address, int length, int type, struct hostent *he, char *buffer, int bufsize,int *errno)

8 arg version: struct hostent *gethostbyaddr_r(char*address, int length, int type, struct hostent *he, char *buffer, int bufsize,struct hostent **hep, int *errno)

gethostbyname_rNot needed on Windows, HP-UX 11 and AIX 5(since gethostbyname() is then thread-safe on its own). Not existant on olderplatforms.
Three different APIs.

AIX4, Digital Unix/Tru64, HPUX 10 use 3 arguments: intgethostbyname_r(char *hostname, struct hostent *hostent, struct hostent_data*data)

Solaris (needs to be linked with -lnsl) and IRIX use 5 arguments: int gethostbyname_r(char *hostname, struct hostent *hostent,char *buffer, int buflen, int *h_errnop)

Linux uses 6 arguments: int gethostbyname_r(const char*name, struct hostent *ret, char *buf, size_t buflen, struct hostent **result,int *h_errnop)

gethostbynameFound in different libs in different operatingsystems. Could be one of these: -lnsl (Solaris), -lsocket, -lws2_32 (Windows),and -lnet (BeOS). See also gethostbyname_r
localtime_rNot present in all unixes. Broken implementationin HPUX 10.20 (it returns an 'int' instead of a pointer - is that 0 forsuccess?)
strerror_rNot present everywhere (like Windows, Solaris7). But when it is, there's a POSIX way (intstrerror_r(int errnum, char *buf, size_t n)) and there's a glibc way(char *strerror_r(int errnum, char *buf, size_tn))
inet_ntoa_rNot present in all unixes.
strtok_rNot present in all unixes. Standardized in UNIX98(aka SUSv2)
getpass_rNot present in all unixes. In fact, this is rarelyavailable. (SCO Unix has it)
gmtime_rBroken implementation in HPUX 10.20 (it returns an'int' instead of a pointer - is that 0 for success?)
selectWindows quirks: you can only select on sockets. Youcannot know if a FD_SET() would overflow the buffer since the file descriptornumbering starts way above 0 and comparisons against FD_SETSIZE are notworking. FD_SETSIZE is typically set very low (64) by default.

Many unix versions allow FD_SETSIZE to be re-defined at compile time, butLinux does not.

Linux has odd semantics, the following is from the BUGS section of select(2)

Under Linux, select() may report a socket file descriptor as "ready for reading", while nevertheless a subsequent read blocks. This could for example happen when data has arrived but upon examination has wrong checksum and is discarded. There may be other circumstances in which a file descriptor is spuriously reported as ready. Thus it may be safer to use O_NONBLOCK on sockets that should not block.

pollNot existing on old unixes. Broken implementation in MacOS X at least up to 10.4 and earlier. Up to 10.3 you could check for a poll()that works with all arguments zeroed. The 10.4 bug is more obscure an I don'tknow of any way to detect it without checking for OS.
snprintfEssential function that is lacking in older unixes(SunOS) and Windows. Different implementations return differen values in caseof prevented overflow. autoconf macrofor C99-compliant snprintf trio *printfcode
sprintfReturns either a 'char *' as a pointer to the outputbuffer (SunOS, 4.3 BSD) or an int as the length of the output data (mostothers, POSIX).
strcasecmpSome platforms (Reliant and UnixWare) have this inthe resolve lib, requiring -lresolve to link fine.
socketNeeds -lnsl -lsocket in LDFLAGS to link onSolaris

On Win64 it returns a SOCKET which is 64 bits, while (all?) other systemsreturn an int, 32 bits.

sigactionHPUX doesn't have SA_RESTART, but instead itdefaults to the same behaviour as other systems that do have gets when ANDingout the SA_RESTART bit from sigact.sa_flags

Concepts

ConceptDescription
Non-blocking socketsDone in lots of different ways:

The POSIX approach (known to not work on SunOS 4, AIX v3 and BeOS - althoughthe function and defines are present) fcntl(socket,F_SETFL, flags | O_NONBLOCK)

BSD-style ioctl(socket, FIONBIO, &flags)

Windows-style ioctlsocket(socket, FIONBIO, &flags)

AmigaOS-style IoctlSocket(socket, FIONBIO, (long)1)

BeOS-style setsockopt(socket, SOL_SOCKET, SO_NONBLOCK, &b, sizeof(b))

Avoiding SIGPIPEDone in several ways:

Ignore signal (usingsigaction() or signal(), the latter more widely available)

Mac OS X 10.2 and later (at least): setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&onoff,sizeof(onoff))

Most other systems support send/recv(x,y,z, MSG_NOSIGNAL)

Building thread-safe-D_THREAD_SAFE -D_REENTRANT (Solaris,HPUX) and more? [FILL IN]
libcWindows quirks: the libc is provided by the compiler, notby the operating system. Thus, various libc function calls may differ betweencompilers.
case insensitive string comparisonsMost systems: int strcasecmp()
Windows: int strcmpi() or int stricmp()
writeable argv[]Many systems allow programs to overwrite theargv[] strings to hide data from appearing in ps outputs (Linux, Solaris 7,HP-UX 11, Tru64 V5, IRIX 6.5)
inlineWas not a standard keyword until C99. Before that,compilers provided various own approaches (gccsupports inline since very long).

Variable Types

TypeIssues
time_tOften a signed 32bit type, sometimes unsigned 32bit(OpenVMS), and sometimes still 32bit even when running in a 64bit arch (AIX)and even sometimes 64bit on 32bit systems (VS2005)
size_tPOSIX type not always present on old systems. strlen()and family returns size_t in POSIX
ssize_tCommonly used signed version of size_t. Not present onnumerous systems.
in_addr_tNot present on many pre-POSIX systems. Functionsthat otherwise use in_addr_t usually use int on those.
socklen_tNot present on many pre-POSIX systems. Functionsthat otherwise use socklen_t usually use int on those.

AIX 4.2 curiously uses an unsigned type for this. (AIX -4.1 was int, AIX 4.3+ is socklen_t)

struct sockaddr_storageNot present in AIX 4.3 even though ithas getaddrinfo() and other IPv6-ready functions
off_tPOSIX type for file sizes. Not present on oldersystems. Usually 32 or 64 bit.

Contributions by
Bjorn Reese, Magnus Fromreide

Thanks!

Latest update: July 30, 2010

daniel at haxx dot .se

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值