C and C++ compilation system

C++ and dynamic linking

Shared objects may be created from C++ source as well as from C source. The foregoing discussion of creating and using C shared objects applies to C++ shared objects also, with two limitations:

Note also that when you have file scope objects of the same name and type in both an a.out and a shared library, the space for the objects is shared (so that there's really only one object), but the constructor for that object is called twice during startup, once from the a.out, once from the .so. (And similarly for the destructor.)

An example would be this:

           #include <stdio.h>

class A { public: A(const char* s) { printf("ctor %s, object %x\n", s, this); } };

so1.C: #include "so.h"

A a("from so1.C");

so2.C: #include "so.h"

A a("from so2.C");

int main() { }

$ CC -G -KPIC -o so1.C $ CC so2.C $ a.out ctor from so1.C, object 8049840 ctor from so2.C, object 8049840

Since this kind of duplicate construction is probably not what was intended, such use of same-named file scope objects is best avoided. (The -Bsymbolic option can be used to create two separate spaces for the objects, but this probably is not what was intended either.)

Building a C++ shared object

The options to the CC command to create and locate shared objects are the same as the options to the cc command. The following command, for example, will create a shared object named from two C++ source files:

   $ CC -G -KPIC -o function1.C function2.C

To avoid dangling references, you should ensure that all templates referenced within a library are instantiated within the library.

Static constructors and destructors

Unlike an archive library, with a shared object the linker cannot determine what subset of functions and objects within a library are actually needed by the program, therefore, all the static constructors (destructors) in the shared object will be executed when the shared object is loaded (unloaded). The static constructors will be called in thereverse of the order the object files appear on the command line used to create the object. For example, given the following command line,

   $ CC -G function1.o function2.o function3.o
the static constructors will be called in the order function3.o function2.o function1.o. When the object is unloaded, the static destructors will be called in the reverse order of the calls to the static constructors, that is, in the order the object files appear on the command line.

When multiple C++ shared objects are loaded, if shared object a depends on shared object b, the static constructors in shared object b will be executed first. There is no guarantee of any ordering of calls to static constructors between unrelated shared objects. When the program exits, the static destructors are called in the reverse order of the calls to the static constructors. If dlclose(3C) is used to explicitly close a shared object, static destructors may be executed out-of-sequence with respect to other static destructors in shared objects that are still open. (The ISO C++ standard considers that dynamic libraries are outside the scope of the standard, which means that behavior such as this does not constitute a violation of the standard.)

Diagnostics from the dynamic linker

The dynamic linker does not demangle any names in the diagnostics it produces. (See

``C++ external function name encoding''.)

If a diagnostic appears somewhat cryptic:

   $ a.out
   dynamic linker: a.out: symbol not found: g__Fv
capture the standard error output and demangle it with the c++filt(C++) filter program:
   $ a.out 2>/var/tmp/a.out.err
   $ c++filt </var/tmp/a.out.err
   dynamic linker: a.out: symbol not found: g(void)

Next topic: C++ external function name encoding
Previous topic: Library maintenance

© 2005 The SCO Group, Inc. All rights reserved.
SCO OpenServer Release 6.0.0 -- 02 June 2005