Chapter 17: Library Introduction

Chapter 17 is actually a list of definitions and descriptions used in the following chapters of the Standard when describing the actual library. Here, we use "Introduction" as an introduction to the GNU implementation of the ISO Standard C++ Library.


The Standard C++ header files

The Standard C++ Library specifies 50 header files that must be available to all hosted implementations. Actually, the word "files" is a misnomer, since the contents of the headers don't necessarily have to be in any kind of external file. The only rule is that when you #include a certain header, the contents of that header, as defined by the Standard, become available to you, no matter how.

The names of the headers can be easily seen in testsuite/17_intro/, which is a small testbed we use to make certain that the headers all compile and run.

The Standard C++ library and multithreading

This section discusses issues surrounding the proper compilation of multithreaded applications which use the Standard C++ library. This information is GCC-specific since the C++ standard does not address matters of multithreaded applications. Unless explicitly prefaced, all information in this section is current as of the GCC 3.0 release and all later point releases.

Earlier GCC releases had a somewhat different approach to threading configuration and proper compilation. Before GCC 3.0, configuration of the threading model was dictated by compiler command-line options and macros (both of which were somewhat thread-implementation and port-specific). There were no guarantees related to being able to link code compiled with one set of options and macro setting with another set. For GCC 3.0, configuration of the threading model used with libraries and user-code is performed when GCC is configured and built using the --enable-threads and --disable-threads options. The ABI is stable for symbol name-mangling and limited functional compatibility exists between code compiled under different threading models.

All normal disclaimers aside, multithreaded C++ application are only supported when libstdc++ and all user code was built with compilers which report (via gcc/g++ -v ) the same thread model and that model is not single. As long as your final application is actually single-threaded, then it should be safe to mix user code built with a thread model of single with a libstdc++ and other C++ libraries built with another thread model useful on the platform. Other mixes may or may not work but are not considered supported. (Thus, if you distribute a shared C++ library in binary form only, it may be best to compile it with a GCC configured with --enable-threads for maximal interchangeability and usefulness with a user population that may have built GCC with either --enable-threads or --disable-threads.)

When you link a multithreaded application, you will probably need to add a library or flag to g++. This is a very non-standardized area of GCC across ports. Some ports support a special flag (the spelling isn't even standardized yet) to add all required macros to a compilation (if any such flags are required then you must provide the flag for all compilations not just linking) and link-library additions and/or replacements at link time. The documentation is weak. Here is a quick summary to display how ad hoc this is: On Solaris, both -pthreads and -threads (with subtly different meanings) are honored. On OSF, -pthread and -threads (with subtly different meanings) are honored. On Linux/i386, -pthread is honored. On FreeBSD, -pthread is honored. Some other ports use other switches. AFAIK, none of this is properly documented anywhere other than in ``gcc -dumpspecs'' (look at lib and cpp entries).

See FAQ (general overview), 23 (containers), and 27 (I/O) for more information.

The libstdc++-v3 library (unlike libstdc++-v2, all of it, not just the STL) has been designed so that multithreaded applications using it may be written. The first problem is finding a fast method of implementation portable to all platforms. Due to historical reasons, some of the library is written against per-CPU-architecture spinlocks and other parts against the gthr.h abstraction layer which is provided by gcc. A minor problem that pops up every so often is different interpretations of what "thread-safe" means for a library (not a general program). We currently use the same definition that SGI uses for their STL subset. However, the exception for read-only containers only applies to the STL components.

Here is a small link farm to threads (no pun) in the mail archives that discuss the threading problem. Each link is to the first relevant message in the thread; from there you can use "Thread Next" to move down the thread. This farm is in latest-to-oldest order.

(A large selection of links to older messages has been removed; many of the messages from 1999 were lost in a disk crash, and the few people with access to the backup tapes have been too swamped with work to restore them. Many of the points have been superseded anyhow.)

This section will be updated as new and interesting issues come to light.

Return to top of page or to the FAQ.

<foo> vs <foo.h>

The new-style headers are fully supported in libstdc++-v3. The compiler itself fully supports namespaces, including std::.

For those of you new to ISO C++98, no, that isn't a typo, the headers really have new names. Marshall Cline's C++ FAQ Lite has a good explanation in item [27.4].

Return to top of page or to the FAQ.

Behavior specific to libstdc++-v3

The ISO standard defines the following phrase:

[1.3.5] implementation-defined behavior
behavior, for a well-formed program construct and correct data, that depends on the implementation and that each implementation shall document.

We do so here, for the C++ library only. Behavior of the compiler, linker, runtime loader, and other elements of "the implementation" are documented elsewhere. Everything listed in Annex B, Implemenation Qualities, are also part of the compiler, not the library.

For each entry, we give the section number of the standard, when applicable. This list is probably incomplet and inkorrekt.

[1.9]/11 #3 If isatty(3) is true, then interactive stream support is implied.

[] Non-reentrant functions are probably best discussed in the various sections on multithreading (see above).

[18.1]/4 The type of NULL is described here.

[18.3]/8 Even though it's listed in the library sections, libstdc++-v3 has zero control over what the cleanup code hands back to the runtime loader. Talk to the compiler people. :-)

[]/5 (bad_alloc),
[18.5.2]/5 (bad_cast),
[18.5.3]/5 (bad_typeid),
[18.6.1]/8 (exception),
[]/5 (bad_exception): The what() member function of class std::exception, and these other classes publicly derived from it, simply returns the name of the class. But they are the mangled names; you will need to call c++filt and pass the names as command-line parameters to demangle them, or call a runtime demangler function. (The classes in <stdexcept> have constructors which require an argument to use later for what() calls, so the problem of what()'s value does not arise in most user-defined exceptions.)

[18.5.1]/7 The return value of std::type_info::name() is the mangled type name (see the previous entry for more).

[20.1.5]/5 "Implementors are encouraged to supply libraries that can accept allocators that encapsulate more general memory models and that support non-equal instances. In such implementations, any requirements imposed on allocators by containers beyond those requirements that appear in Table 32, and the semantics of containers and algorithms when allocator instances compare non-equal, are implementation-defined." As yet we don't have any allocators which compare non-equal, so we can't describe how they behave.

[23.*]'s foo::iterator,
[27.*]'s foo::*_type,
others... Nope, these types are called implementation-defined because you shouldn't be taking advantage of their underlying types. Listing them here would defeat the purpose. :-)

[]/5 I don't really know about the mbstate_t stuff... see the chapter 22 notes for what does exist.

[22.*] Anything and everything we have on locale implemenation will be described over here.

[26.2.8]/9 I have no idea what complex<T>'s pow(0,0) returns.

[]/2 Calling std::ios_base::sync_with_stdio after I/O has already been performed on the standard stream objects will flush the buffers, and destroy and recreate the underlying buffer instances. Whether or not the previously-written I/O is destroyed in this process depends mostly on the --enable-libio choice: for stdio, if the written data is already in the stdio buffer, the data may be completely safe!

[] The I/O sentry ctor and dtor can perform additional work than the minimum required. We are not currently taking advantage of this yet.

[]/10 The effects of pubsetbuf/setbuf are described in this chapter.

[]/16 Calling fstream::sync when a get area exists will... whatever fflush() does, I think.

Return to top of page or to the FAQ.

Preprocessor macros controlling the library

Some of the semantics of the libstdc++-v3 implementation are controlled by preprocessor macros, both during build/installation and during compilation of user code. Many of these choices are made when the library is built and installed (actually, during the configuration step, with the various --enable/--disable choices being translated to #define/#undef).

All library macros begin with _GLIBCPP_ in earlier versions, and _GLIBCXX_ in later versions. The fact that these symbols start with a leading underscore should give you a clue that (by default) they aren't meant to be changed by the user. :-)

These macros are all gathered in the file c++config.h, which is generated during installation. You must assume that these macros cannot be redefined by your own code, unless we document otherwise here. Some of the choices control code which has already been compiled (i.e., libstdc++.a/.so). If you explicitly #define or #undef these macros, the headers may see different code paths, but the libraries which you link against will not. If you want to experiment with different values, you must change the config headers before building/installing the library.

Below are macros which, for 3.1 and later, you may change yourself, in your own code with #define/#undef or with -D/-U compiler flags. The default state of the symbol is listed. "Configurable" (or "Not configurable") means that the symbol is initially chosen (or not) based on --enable/--disable options at configure time. For 3.1 through 3.3, the prefixes are _GLIBCPP_.

Undefined by default. Not configurable. Turning this on enables older ARM-style iostreams code, and other anachronisms. This may be useful in updating old C++ programs which no longer meet the requirements of the language.
Undefined by default. Configurable. When defined, performs compile-time checking on certain template instantiations to detect violations of the requirements of the standard. This is described in more detail here.
Undefined by default. Configurable. When defined, compiles user code using the libstdc++ debug mode.
Undefined by default. Configurable. When defined while compiling with the libstdc++ debug mode, makes the debug mode extremely picky by making the use of libstdc++ extensions and libstdc++-specific behavior into errors.

Return to top of page or to the FAQ.

See license.html for copying conditions. Comments and suggestions are welcome, and may be sent to the libstdc++ mailing list.