GLIBC is a library of functions used by many Linux packages. Each new release contains bug fixes and new features. While code compiled with an older GLIBC will work with a new GLIBC the inverse is not true. This is where the trouble starts....
GLIBC cannot be upgraded (or at least its not recommended) and asking customers who receive your code to upgrade GLIBC or the OS is a real hassle. So let's do a dive in to the version numbers...
GLIBC VersionsTo check your GLIBC version run one of the following commands. Notice they are from different OS version since 2.5 representes RHEL 5 and 2.12 represents RHEL 6. For a full history of versions click this link.
$ ldd --version
ldd (GNU libc) 2.12 Copyright (C) 2010 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Written by Roland McGrath and Ulrich Drepper.
$ /lib/libc.so.6 GNU C Library stable release version 2.5, by Roland McGrath et al. Copyright (C) 2006 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. Compiled by GNU CC version 4.1.2 20080704 (Red Hat 4.1.2-50). Compiled on a Linux 2.6.9 system on 2012-01-19. Available extensions: The C stubs add-on version 2.1.2. crypt add-on version 2.1 by Michael Glad GNU Libidn by Simon Josefsson GNU libio by Per Bothner NIS(YP)/NIS+ NSS modules 0.19 by Thorsten Kukuk Native POSIX Threads Library by Ulrich Drepper et al BIND-8.2.3-T5B RT using linux kernel aio Thread-local storage support included. For bug reporting instructions, please see: http://www.gnu.org/software/libc/bugs.html.
Viewing your dependencies...When building a C/C++ application on a RHEL6 box you are automatically binding to the GLIBC 2.12 library. However... this doesn't mean you app will fail to work on RHEL5. It very much depends on the functions you use. If you choose a function that's only in GLIBC 2.12 then you have automatically tied yourself to newer OS versions.
BUT WAIT... What if I didn't use a new function! I just have a plain old C program but it won't run. This is likely due to libraries you may link with that are also compiled on RHEL6.
To view your dependencies run the program nm or objdump. Objdump will show your overall dependencies and nm will show specific function dependencies. Both programs allow you to quickly home in on the function that will not run on older Linux servers (compare the GLIBC version).
Once you find the offending function you can grep -R for it in your libraries and binaries to figure out what third party code polluted your build!
$ objdump -p mybin
mybin: file format elf64-x86-64
required from libgcc_s.so.1:
0x0b792650 0x00 07 GCC_3.0
required from libpthread.so.0:
0x09691a75 0x00 06 GLIBC_2.2.5
required from libc.so.6:
0x0d696913 0x00 05 GLIBC_2.3
0x09691a75 0x00 04 GLIBC_2.2.5
required from libstdc++.so.6:
0x08922974 0x00 03 GLIBCXX_3.4
0x056bafd3 0x00 02 CXXABI_1.3
$ nm mybin
00000000006124f0 V DW.ref._ZTIN6oracle4occi12SQLExceptionE
00000000006124f8 V DW.ref.__gxx_personality_v0
000000000040e575 t I_comp
0000000000612038 d _DYNAMIC
0000000000612290 d _GLOBAL_OFFSET_TABLE_
00000000004032d0 t _GLOBAL__I_occi_db.cpp
0000000000401f90 t _GLOBAL__I_occi_port.cpp
000000000040f280 R _IO_stdin_used
w _Jv_RegisterClasses0000000000405dfd t pvariable
0000000000405d95 t release_chain
0000000000405bae t strsave
000000000040d135 t to_float
0000000000405d46 t undo_bindings
0000000000612754 b use_fallback.4930
Solution for __isoc99_sscanfThe function __isoc99_sscanf caused me a lot of trouble. A library I was linking to was compiled with RHEL6 and GLIBC 2.12. I used objdump and nm (see above) to locate the offending function... __isoc99_sscanf
The GCC/G++ compiler I was using had a change in one of the header files regarding scanf such that any builds now required __isoc99_sscanf and GLIBC 2.12... locking me in to RHEL6 and breaking RHEL5 compatibility.
The solution is simple... define the following #define...
#define _GNU_SOURCE 1
or adjust your makefile CFLAGS/CPPFLAGS/CXXFLAGS...
This alters the behavior of the sscanf code block stdio.h by setting __USE_GNU to TRUE (an internal macro that is enabled when _GNU_SOURCE is defined). The macro prevents the __isoc99_sscanf redefinition and saves us from compatibility hell! :-)
#if defined __USE_ISOC99 && !defined __USE_GNU \
&& (!defined __LDBL_COMPAT || !defined __REDIRECT) \
&& (defined __STRICT_ANSI__ || defined __USE_XOPEN2K)
/* For strict ISO C99 or POSIX compliance disallow
%as, %aS and %a[ GNU extension which conflicts
with valid %a followed by letter s, S or [. */
extern int __isoc99_sscanf (__const char *__restrict __s,
__const char *__restrict __format, ...) __THROW;
# define sscanf __isoc99_sscanf