1

I'm working on C and C++ programs which need to run on several different embedded platforms, for which I have cross-complilers so I can do the build on my x86 desktop.

I have a horrible problem with certain functions, e.g. "strtod()". Here's my simple test program:

#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv)
  {
  if ( (argc < 2) || (NULL == argv[1]) ) return 0; 
  double myDouble = strtod(argv[1], NULL);
  printf("\nValue: %f\n\n", myDouble);
  return 0;
  }

Normally I build all programs with dynamic linking to keep the binaries as small as possible. The above works fine on the x86 and Power PC. However, on the Arm system (BeagleBoard xM with Debian) strtod() misbehaves (the program always outputs "0.000000").

I tried building the program with the option '-static', and that worked on the Beagle:

root@beaglexm:/app# ./test.dynamic 1.23
Value: 0.000000
  [Dynamic linked version - WRONG!!]

root@beaglexm:/app# ./test.static 1.23
Value: 1.230000
  [Correct!!]

I also tested on a BeagleBone Black, which has a slightly different distribution. Both versions (static and dynamic) worked fine on the BBB.

Digging around in the libraries, I found the following version numbers:

Cross Compiler Toolchain: libc-2.9.so

BeagleBoard XM (DOESN'T WORK): libc-2.13.so

BeagleBone Black (WORKS!): libc-2.16.so

So my cross compiler is building against an older version of glibc. I've read in several places that glibc should be backwards-compatible.

I thought about static linking only libc, but according to this question it's a bad idea unless all libraries are statically linked.

Static linking everything does work, but there are serious constraints on the system which mean I need to keep the binaries as small as possible.

Any ideas what would cause horrible problems with strtod() (and similar functions) and/or why glibc 2.13 is not backwards compatible?

EDIT: I didn't mention that the "soname" (i.e. top level name) is the same on all platforms: "libc.so.6" From my reading of the docs, the number AFTER the .so in the "soname" is the major version and only changes if the interface changes - hence all these versions should be compatible. The number BEFORE the .so which appears in the actual file name (shown above, and found by following the symlink) is the minor version. See: link

Community
  • 1
  • 1
Jeremy
  • 1,083
  • 3
  • 13
  • 25

1 Answers1

3

Generally version numbers reflect compatibility. The number that appears between the .so and the next dot represents a MAJOR revision, not guaranteed compatible with any other major revision.

The number(s) that that follow that, which you'll only see if you follow the symbolic links, represents a MINOR revision. These can be used interchangably, and symlinks are used to do just that. The program links against libc.so.6 or whatever, and on the actual filesystem, libc.so.6 is a symbolic link to (for example) libc.so.6.12.

glibc tries to maintain compatibility even across major revisions, but there are times when they simply have to accept a breaking change. Typically this would be when a new version of the C or POSIX standards are released and function signatures get updated in a way that breaks binary compatibility.

Any numbers that appear before the .so will also break compatibility if changed; these usually represent a complete rewrite of a program. For example glib vs glib2. Not of concern for libc.

The tool ldd is very useful for investigating library dependencies and discovering while exact version of the library is actually being loaded.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Although I can't disagree with anything in your answer, it hardly answers the question. – rubenvb Dec 01 '14 at 08:28
  • @rubenvb: Sure it does. "Why is glibc not backwards compatible? Because *new versions of the C standard*" – Ben Voigt Dec 01 '14 at 18:31
  • 1
    I didn't mention that the "soname" (i.e. top level name) is the same on all platforms: "libc.so.6" From my reading of the docs, you have your version numbers around the wrong way. See the comment I added to the question. As I read it, they should all be compatible. – Jeremy Dec 01 '14 at 18:41
  • @Jeremy: Those "numbers the wrong way" came straight from your question, although you're right I had some problems in the explanation as well. As yes, if they all are `libc.so.6.x`, then they are expected to maintain compatibility. Someone didn't notice that one of the changes was a breaking change, and therefore didn't roll the major library number. – Ben Voigt Dec 01 '14 at 21:22
  • Heh, that was my suspicion - i.e. "it doesn't work because it's broken". Still hoping I've missed something and there is an easy fix, but currently trying to obtain the exact toolchain for the problematic platform and see if that works. – Jeremy Dec 01 '14 at 22:43