C/C++ Dependency Troubleshooting

Unix C/C++ programs are very finicky about the compiler and library versions.  Compiling is the process of translating human readable code into a binary executable or library that contains machine-friendly instructions.  Linking is the process of telling multiple executables or libraries how to talk to each other.

gcc is a GNU C compiler that is typically used on unix systems. g++ is a GNU C++ compiler on unix systems.  libstdc++ is the GNU standard C++ library.   glibc is the GNU standard C library.  When you install GCC on your unix machine, you are installing a package of the aforementioned items.  The gcc unix command is smart enough to call either the gcc compiler or g++ compiler depending if you pass it C or C++ code.

If you attempt to run your program with an older standard library than it was originally linked it with, your program will crash and complain.  Here are some tips to get around it.

My C++ Program Fails to Find the Right GLIBCXX Version

If your program was originally linked to a newer libstdc++ than your current system uses, you may get errors similar to this when you run your program:

Discovar: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.18' not found (required by Discovar)
Discovar: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by Discovar)

GLIBCXX_* are the ELF version strings used by libstdc++. C/C++ libraries and executables use ELF version strings to specify version information for their contents.

In the previous example, the program being run is Discovar.  Discovar is trying to link to the current standard C++ library in /usr/lib/libstd++.so.6.  The current libstdc++ is an older version that does not contain ELF version info  GLIBCXX_3.4.18 and GLIBCXX_3.4.15.   Discovar was originally linked with a newer libstdc++ containing those ELF versions and crashes because it can’t find them anymore.  From the  libstdc++ filename above, you can only ascertain the major revision of the libstdc++ file:  /usr/lib/libstd++.so.6  indicates the system is using libstdc++ version 6.X.X.  Note that the file version numbering (6.X.X) is separate from the content version numbering (GLIBCXX 3.4.X).

You can find all locations that your program is trying to find libstdc++ by executing the following:

# /sbin/ldconfig -p | grep stdc++
    libstdc++.so.6 (libc6,x86-64) => /usr/lib/libstdc++.so.6
    libstdc++.so.6 (libc6) => /usr/lib32/libstdc++.so.6
    libstdc++.so.5 (libc6) => /usr/lib32/libstdc++.so.5

You can find the full major and minor revision numbers of your libstdc++ by checking the full file-path pointed to by the symlink.  Below, the libstdc++ version is 6.0.18.

$ ls -lht /usr/local/lib32/libstdc++.so.6
lrwxrwxrwx 1 root staff 19 Jun 12 22:28 /usr/local/lib32/libstdc++.so.6 -> libstdc++.so.6.0.18

Find which GLIBCXX versions a libstd++ exports by executing the following.  It prints all the human readable symbols from the binary:

$ strings /usr/lib/libstdc++.so.6 | grep GLIBC
GLIBCXX_3.4
GLIBCXX_3.4.1
GLIBCXX_3.4.2
GLIBCXX_3.4.3
GLIBCXX_3.4.4
GLIBCXX_3.4.5
GLIBCXX_3.4.6
GLIBCXX_3.4.7
GLIBCXX_3.4.8
GLIBCXX_3.4.9
GLIBCXX_3.4.10
GLIBCXX_3.4.11
GLIBCXX_3.4.12
GLIBCXX_3.4.13
GLIBCXX_3.4.14
GLIBC_2.2.5
GLIBC_2.3
GLIBC_2.4
GLIBC_2.3.4
GLIBC_2.3.2
GLIBCXX_FORCE_NEW
GLIBCXX_DEBUG_MESSAGE_LENGTH

This indicates that /usr/lib/libstdc++.so.6 exports symbols for GLIBCXX versions up to 3.4.14.

In order to get GLIBCXX 3.4.18 or 3.4.15 as required by the program throwing the error, we need to update libstdc++ on our system. The best way to do this is to use yum or apt-get or whatever package manager your Unix uses to install the latest gcc package.  Using the official package manager will ensure that all required files get placed in default locations searched by the compiler and linker.  You can have multiple gcc/g++ and glibc/libstdc++ versions on your system.

If you installed the gcc package manually by compiling from source, it will come with the required standard C/C++ libraries, but those libraries will most likely be installed under /usr/local/…, which is not search by default by the linker.  Even though the compiler program gcc will be installed correctly, you will not be able to run any programs that require the newer compiler and standard libraries, because the linker will not be able to find the newer standard libraries.

Explicitly tell the linker where to search for libraries by modifying your LD_LIBRARY_PATH environment variable (bash shell):

$export  LD_LIBRARY_PATH=/usr/local/lib64

Replace /usr/local/lib64 with the parent folder of your desired libstdc++ file.

How Do I Check my GLIBC Version

Glibc the Gnu Standard C Library for unix. It is different from GLIBCXX (libstdc++). If your C program was linked to a later version of glibc than your system currently uses, your program will complain about glibc errors when you run it.

In order to check which version of glibc you have installed on Ubuntu, execute this:

$ /lib/libc.so.6
GNU C Library (Ubuntu EGLIBC 2.12.1-0ubuntu10.4) stable release version 2.12.1, by Roland McGrath et al.
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.
Compiled by GNU CC version 4.4.5.
Compiled on a Linux 2.6.35 system on 2012-03-06.
Available extensions:
    crypt add-on version 2.1 by Michael Glad and others
    GNU Libidn by Simon Josefsson
    Native POSIX Threads Library by Ulrich Drepper et al
    BIND-8.2.3-T5B
libc ABIs: UNIQUE IFUNC
For bug reporting instructions, please see:
<http://www.debian.org/Bugs/>.

Reference: http://ubuntuforums.org/showthread.php?t=1173797

How Do I Find and Resolve Linking Dependencies

To find out which missing library dependencies for your program, execute the following:

# ldd <Program executable or binary> 
/usr/local/bin/Discovar: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.18' not found (required by /usr/local/bin/Discovar)
/usr/local/bin/Discovar: /usr/lib/libstdc++.so.6: version `GLIBCXX_3.4.15' not found (required by /usr/local/bin/Discovar)
    linux-vdso.so.1 =>  (0x00007fff85375000)
    libstdc++.so.6 => /usr/lib/libstdc++.so.6 (0x00007fb8de130000)
    libm.so.6 => /lib/libm.so.6 (0x00007fb8ddead000)
    libgomp.so.1 => /usr/lib/libgomp.so.1 (0x00007fb8ddc9e000)
    libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x00007fb8dda88000)
    libpthread.so.0 => /lib/libpthread.so.0 (0x00007fb8dd86b000)
    libc.so.6 => /lib/libc.so.6 (0x00007fb8dd4e6000)
    /lib64/ld-linux-x86-64.so.2 (0x00007fb8de459000)
    librt.so.1 => /lib/librt.so.1 (0x00007fb8dd2de000)

You can tell your program how to find the missing libraries by modifying your LD_LIBRARY_PATH environment variable to include their parent directories.