Go to the first, previous, next, last section, table of contents.

# User Problems

- missing virtual table
- for scope
- const constructor
- unused parameter warnings
- jump crosses initialization
- Demangler
- static data members
- internal compiler error
- bug reports
- porting to g++
- name mangling
- problems linking with other libraries
- documentation
- templates
- undefined templates
- redundant templates
- Standard Template Library
- STL and string
- exceptions
- namespaces
- agreement with standards
- compiling standard libraries
- debugging on SVR4 systems
- debugging problems on Solaris
- X11 conflicts with libg++
- assignment to streams

## Linker complains about missing virtual table

"I'm getting a message complaining about an undefined virtual table. Is this a compiler bug?"

(On platforms that run neither collect nor the GNU linker, like Solaris, you may see an odd undefined symbol like "_vt.3foo", where foo is a class name).

This is probably because you are missing a definition for the first (non-inline) virtual function of the class. Since gcc-2.7.0, g++ uses a trick borrowed from cfront: the .o file containing the definition for the first non-inline virtual function for the class will also contain the virtual function table.

## gcc-2.7.0 breaks declarations in "for" statements!

gcc-2.7.0 implements the new ANSI/ISO rule on the scope of variables declared in for loops.

    for (int i = 1; i <= 10; i++) {
            // do something here
    }
    foo(i);

In the above example, most existing C++ compilers would pass the value 11 to the function `foo`. In gcc 2.7 and in the ANSI/ISO working paper, the scope of `i` is only the for loop body, so this is an error. So that old code can be compiled, the new gcc has a flag `-fno-for-scope` that causes the old rule to be used.

As of 2.7.1, the compiler attempts to issue warnings about code that has different meanings under the two sets of rules, but the code is not perfect: the intent was that code that has valid, but different, meanings under the ARM rules and the working paper rules would give warnings but have the new behavior, and this doesn't seem to happen.

The `-ffor-scope` flag under 2.7.1 and 2.7.2 gives the 2.7.0 behavior.

## g++ seems to want a const constructor. What's that?

gcc-2.7.1 introduced a bug that causes the compiler to ask for a const constructor (there's no such thing in C++) in certain situations where a const object appears in a template class. Most cases have been fixed in gcc-2.7.2, but unfortunately not all. Still, if you're running gcc-2.7.1 and have this problem, upgrade to 2.7.2; it is a vast improvement.

The default constructor for the template `pair` in ObjectSpace's implementation of STL triggers the bug in one place, for gcc 2.7.2. If you're using ObjectSpace<STL> and having this problem, simply change the default constructor from

    os_pair () : first (T1 ()), second (T2 ()) {}

to just

    os_pair () {}

Once this is done, ObjectSpace<STL> works fairly well.

## How to silence "unused parameter" warnings

"When I use `-Wall` (or `-Wunused`), g++ warns about unused parameters. But the parameters have to be there, for use in derived class functions. How do I get g++ to stop complaining?"

The answer is to simply omit the names of the unused parameters when defining the function. This makes clear, both to g++ and to readers of your code, that the parameter is unused. For example:

    int Foo::bar(int arg) { return 0; }

will give a warning for the unused parameter `arg`. To suppress the warning write

    int Foo::bar(int) { return 0; }

## g++ objects to a declaration in a case statement

"The compiler objects to my declaring a variable in one of the branches of a case statement. Earlier versions used to accept this code. Why?"

The draft standard does not allow a goto or a jump to a case label to skip over an initialization of a variable or a class object. For example:

    switch ( i ) {
      case 1:
        Object obj(0);
            ...
        break;
      case 2:
    	...
        break;
    }

The reason is that `obj` is also in scope in the rest of the switch statement.

As of version 2.7.0, the compiler will object that the jump to the second case level crosses the initialization of `obj`. Older compiler versions would object only if class Object has a destructor. In either case, the solution is to add a set of curly braces around the case branch:

      case 1:
        {
           Object obj(0);
            ...
           break;
        }

## Where can I find a demangler?

A g++-compatible demangler named `c++filt` can be found in the ``binutils'` distribution. This distribution (which also contains the GNU linker) can be found at any GNU archive site.

As of version 2.7.0, `c++filt` is included with gcc and is installed automatically. Even better, it is used by the `collect` linker, so you don't see mangled symbols anymore (except on platforms that use neither collect nor the GNU linker, like Solaris).

## Linker reports undefined symbols for static data members

"g++ reports undefined symbols for all my static data members when I link, even though the program works correctly for compiler XYZ. What's going on?"

The problem is almost certainly that you don't give definitions for your static data members. If you have

    class Foo {
    	...
    	void method();
    	static int bar;
    };

you have only declared that there is an int named Foo::bar and a member function named Foo::method that is defined somewhere. You still need to define both method() and bar in some source file. According to the draft ANSI standard, you must supply an initializer, such as

    int Foo::bar = 0;

in one (and only one) source file.

## What does "Internal compiler error" mean?

It means that the compiler has detected a bug in itself. Unfortunately, g++ still has many bugs, though it is a lot better than it used to be. If you see this message, please send in a complete bug report (see next section).

## I think I have found a bug in g++.

"I think I have found a bug in g++, but I'm not sure. How do I know, and who should I tell?"

First, see the excellent section on bugs and bug reports in the gcc manual (which is included in the gcc distribution). As a short summary of that section: if the compiler gets a fatal signal, for any input, it's a bug (newer versions of g++ will ask you to send in a bug report when they detect an error in themselves). Same thing for producing invalid assembly code.

When you report a bug, make sure to describe your platform (the type of computer, and the version of the operating system it is running) and the version of the compiler that you are running. See the output of the command `g++ -v` if you aren't sure. Also provide enough code so that the g++ maintainers can duplicate your bug. Remember that the maintainers won't have your header files; one possibility is to send the output of the preprocessor (use `g++ -E` to get this). This is what a "complete bug report" means.

I will add some extra notes that are C++-specific, since the notes from the gcc documentation are generally C-specific.

First, mail your bug report to "bug-g++@prep.ai.mit.edu". You may also post to ``gnu.g++.bug'`, but it's better to use mail, particularly if you have any doubt as to whether your news software generates correct reply addresses. Don't mail C++ bugs to bug-gcc@prep.ai.mit.edu.

News: as I write this (late February 1996) the gateway connecting the bug-g++ mailing list and the ``gnu.g++.bug'` newsgroup is (temporarily?) broken. Please mail, do not post bug reports.

If your bug involves libg++ rather than the compiler, mail to bug-lib-g++@prep.ai.mit.edu. If you're not sure, choose one, and if you guessed wrong, the maintainers will forward it to the other list.

Second, if your program does one thing, and you think it should do something else, it is best to consult a good reference if in doubt. The standard reference is the draft working paper from the ANSI/ISO C++ standardization committee, which you can get on the net. For PostScript and PDF (Adobe Acrobat) versions, see the archive at ``ftp://research.att.com/dist/stdc++/WP'`. For HTML and ASCII versions, see ``ftp://ftp.cygnus.com/pub/g++'`. On the World Wide Web, see ``http://www.cygnus.com/misc/wp/'`.

An older standard reference is "The Annotated C++ Reference Manual", by Ellis and Stroustrup (copyright 1990, ISBN #0-201-51459-1). This is what they're talking about on the net when they refer to "the ARM". But you should know that vast changes have been made to the language since then.

The ANSI/ISO C++ standards committee have adopted some changes to the C++ language since the publication of the original ARM, and newer versions of g++ (2.5.x and later) support some of these changes, notably the mutable keyword (added in 2.5.0), the bool type (added in 2.6.0), and changes in the scope of variables defined in for statements (added in 2.7.0). You can obtain an addendum to the ARM explaining many of these changes by FTP from ``ftp://ftp.std.com/AW/stroustrup2e/new_iso.ps'`.

Note that the behavior of (any version of) AT&T's "cfront" compiler is NOT the standard for the language.

## Porting programs from other compilers to g++

"I have a program that runs on <some other C++ compiler>, and I want to get it running under g++. Is there anything I should watch out for?"

Note that g++ supports many of the newer keywords that have recently been added to the language. Your other C++ compiler may not support them, so you may need to rename variables and members that conflict with these keywords.

There are two other reasons why a program that worked under one compiler might fail under another: your program may depend on the order of evaluation of side effects in an expression, or it may depend on the lifetime of a temporary (you may be assuming that a temporary object "lives" longer than the standard guarantees). As an example of the first:

    void func(int,int);

    int i = 3;
    func(i++,i++);

Novice programmers think that the increments will be evaluated in strict left-to-right order. Neither C nor C++ guarantees this; the second increment might happen first, for example. func might get 3,4, or it might get 4,3.

The second problem often happens with classes like the libg++ String class. Let's say I have

    String func1();
    void func2(const char*);

and I say

    func2(func1());

because I know that class String has an "operator const char*". So what really happens is

    func2(func1().convert());

where I'm pretending I have a convert() method that is the same as the cast. This is unsafe in g++ versions before 2.6.0, because the temporary String object may be deleted after its last use (the call to the conversion function), leaving the pointer pointing to garbage, so by the time func2 is called, it gets an invalid argument.

Both the cfront and the old g++ behaviors are legal according to the ARM, but the powers that be have decided that compiler writers were given too much freedom here.

The ANSI C++ committee has now come to a resolution of the lifetime of temporaries problem: they specify that temporaries should be deleted at end-of-statement (and at a couple of other points). This means that g++ versions before 2.6.0 now delete temporaries too early, and cfront deletes temporaries too late. As of version 2.6.0, g++ does things according to the new standard.

For now, the safe way to write such code is to give the temporary a name, which forces it to live until the end of the scope of the name. For example:

    String& tmp = func1();
    func2(tmp);

Finally, like all compilers (but especially C++ compilers, it seems), g++ has bugs, and you may have tweaked one. If so, please file a bug report (after checking the above issues).

## Why does g++ mangle names differently from other C++ compilers?

See the answer to the next question.

## Why can't g++ code link with code from other C++ compilers?

"Why can't I link g++-compiled programs against libraries compiled by some other C++ compiler?"

Some people think that, if only the FSF and Cygnus Support folks would stop being stubborn and mangle names the same way that, say, cfront does, then any g++-compiled program would link successfully against any cfront-compiled library and vice versa. Name mangling is the least of the problems. Compilers differ as to how objects are laid out, how multiple inheritance is implemented, how virtual function calls are handled, and so on, so if the name mangling were made the same, your programs would link against libraries provided from other compilers but then crash when run. For this reason, the ARM encourages compiler writers to make their name mangling different from that of other compilers for the same platform. Incompatible libraries are then detected at link time, rather than at run time.

## What documentation exists for g++ 2.x?

Relatively little. While the gcc manual that comes with the distribution has some coverage of the C++ part of the compiler, it focuses mainly on the C compiler (though the information on the "back end" pertains to C++ as well). Still, there is useful information on the command line options and the #pragma interface and #pragma implementation directives in the manual, and there is a useful section on template instantiation in the 2.6 version. There is a Unix-style manual entry, "g++.1", in the gcc-2.x distribution; the information here is a subset of what is in the manual.

You can buy a nicely printed and bound copy of this manual from the FSF; see above for ordering information.

A draft of a document describing the g++ internals appears in the gcc distribution (called g++int.texi); it is incomplete but gives lots of information.

For class libraries, there are several resources available:

- The libg++ distribution has a manual ``libg++/libg++.texi'` describing the old libg++ classes, and another manual ``libio/iostream.texi'` describing the iostreams implementation.
- While there is no libg++-specific document describing the STL implementation, SGI's web site, at ``http://www.sgi.com/Technology/STL/'`, is an excellent resource. Note that the SGI version of STL is the one that is included with the egcs and 2.8.x releases of g++/libstdc++.

## Problems with the template implementation

g++ does not implement a separate pass to instantiate template functions and classes at this point; for this reason, it will not work, for the most part, to declare your template functions in one file and define them in another. The compiler will need to see the entire definition of the function, and will generate a static copy of the function in each file in which it is used.

(The experimental template repository code (see section How do I use the new repository code?) that can be added to 2.7.0 or later does implement a separate pass, but there is still no searching of files that the compiler never saw).

As of 2.8.x and egcs-1.0.x, the template implementation has most of the features specified in the draft standard. Still missing are template arguments that are themselves templates; however, template class member functions work, and most of the limitations of the older g++ versions are fixed.

I think that given this new implementation, it should not be necessary for users to mess around with switches like `-fno-implicit-templates` and `#pragma` directives; most of the time, the default behavior will work OK. Users of older versions might want to read on.

For version 2.6.0, however, a new switch `-fno-implicit-templates` was added; with this switch, templates are expanded only under user control. I recommend that all g++ users that use templates read the section "Template Instantiation" in the gcc manual (version 2.6.x and newer). g++ now supports explicit template expansion using the syntax from the latest C++ working paper:

    template class A<int>;
    template ostream& operator << (ostream&, const A<int>&);

As of version 2.7.2, there are still a few limitations in the template implementation besides the above (thanks to Jason Merrill for this info):

Note: these problems are eliminated in egcs and in gcc-2.8.x.

1. Static data member templates are not supported in compiler versions older than 2.8.0. You can work around this by explicitly declaring the static variable for each template specialization:

       template <class T> struct A {
         static T t;
       };

       template <class T> T A<T>::t = 0; // gets bogus error
       int A<int>::t = 0;                // OK (workaround)

2. Template member names are not available when defining member function templates.

       template <class T> struct A {
         typedef T foo;
         void f (foo);
         void g (foo arg) { ... }; // this works
       };

       template <class T> void A<T>::f (foo) { } // gets bogus error

3. Templates are instantiated using the parser. This results in two problems (again, these problems are fixed in 2.8.0 and egcs): a) Class templates are instantiated in some situations where such instantiation should not occur.

       template <class T> class A { };
       A<int> *aip = 0; // should not instantiate A<int> (but does)

   b) Function templates cannot be inlined at the site of their instantiation.

       template <class T> inline T min (T a, T b) { return a < b ? a : b; }

       void f () {
         int i = min (1, 0);           // not inlined
       }

       void g () {
         int j = min (1, 0);           // inlined
       }

   A workaround that works in version 2.6.1 through 2.7.2.x is to specify

       extern template int min (int, int);

   before `f()`; this will force it to be instantiated (though not emitted). Note: this kind of "guiding declaration" is not standard and isn't supported by egcs or gcc-2.8.x, as the standard says that this declares a "normal" `min` function which has no relation to the template function `min<int>(int,int)`. But then the new compilers have no problem inlining template functions.
4. Member function templates are always instantiated when their containing class is. This is wrong (fixed in egcs/2.8).

## I get undefined symbols when using templates

(Thanks to Jason Merrill for this section).

g++ does not automatically instantiate templates defined in other files. Because of this, code written for cfront will often produce undefined symbol errors when compiled with g++. You need to tell g++ which template instances you want, by explicitly instantiating them in the file where they are defined. For instance, given the files

``templates.h'`:

    template <class T>
    class A {
    public:
      void f ();
      T t;
    };

    template <class T> void g (T a);

``templates.cc'`:

    #include "templates.h"

    template <class T>
    void A<T>::f () { }

    template <class T>
    void g (T a) { }

main.cc:

    #include "templates.h"

    main ()
    {
      A<int> a;
      a.f ();
      g (a);
    }

compiling everything with `g++ main.cc templates.cc` will result in undefined symbol errors for ``A<int>::f ()'` and ``g (A<int>)'`. To fix these errors, add the lines

    template class A<int>;
    template void g (A<int>);

to the bottom of ``templates.cc'` and recompile.

## I get multiply defined symbols using templates

You may be running into a bug that was introduced in version 2.6.1 (and is still present in 2.6.3) that generated external linkage for templates even when neither `-fexternal-templates` nor `-fno-implicit-templates` is specified. There is a patch for this problem at
``ftp://ftp.cygnus.com/pub/g++/gcc-2.6.3-template-fix'`.

I recommend either applying the patch or using `-fno-implicit-templates` together with explicit template instantiation as described in previous sections.

This bug is fixed in 2.7.0.

## Does g++ support the Standard Template Library?

If you want to use the Standard Template Library, do not pass go, upgrade immediately to gcc-2.8.x or to egcs. The new C++ front end handles STL very well, and the high-quality implementation of STL from SGI is included verbatim as part of the libstdc++ class library.

If for some reason you must use 2.7.2, you can probably get by with the hacked-up version of the old implementation from HP that is included with libg++-2.7.2, but it is definitely inferior and has more problems. Alternatively, g++ 2.7.2.x users might try the following: a group at the Moscow Center for Sparc Technology has a port of the SGI STL implementation that mostly works with gcc-2.7.2. See ``http://www.ipmce.su/people/fbp/stl/stlport.html'`.

Mumit Khan has produced an "STL newbie guide" with lots of information on using STL with gcc. See

``http://www.xraylith.wisc.edu/~khan/software/stl/STL.newbie.html'`

## I'm having problems mixing STL and the standard string class

[ This section is for g++ 2.7.2.x users only ]

This is due to a bug in g++ version 2.7.2 and 2.7.2.1; the compiler is confused by the operator declarations. There is an easy workaround, however; just make sure that the `<string>` header is included before any STL headers. That is, just say

    #include <string>

before any other `#include` directives.

Unfortunately, this doesn't solve all problems; you may still have difficulty with the relational operators !=, <=, >, and >=, thanks to a conflict with the very general definition of these operators in function.h. One trick that sometimes works is to try to use == and < in your code instead of the other operators. Another is to use a derived class of <string>. The only completely satisfactory solution, I'm afraid, is to wait for the new release.

## Problems and limitations with exceptions

The first really usable exceptions implementations are in 2.8.x and egcs. With these versions, exceptions are enabled by default; use -fno-exceptions to disable exceptions.

However, 2.8.1 still has not integrated egcs work that computes an accurate control flow graph in the presence of exceptions. For this reason, you will sometimes get bogus warnings when compiling with 2.8.1, -O, and -Wall, about uninitialized variables and the like.

2.7.2.x has very limited and partially broken support for exceptions. With that compiler, you must provide the `-fhandle-exceptions` flag to enable exception handling. In version 2.7.2 and older, exceptions may not work properly (and you may get odd error messages when compiling) if you turn on optimization (the `-O` flag). If you care about exceptions, please upgrade to a newer compiler!

In 2.7.2, you must give the `-frtti` switch to enable catching of derived exception objects with handlers for the base exception class; if `-frtti` is not given, only exact type matching works.

For exception handling to work with 2.7.0 your CPU must be a SPARC, RS6000/PowerPC, 386/486/Pentium, or ARM. Release 2.7.1 added support for the Alpha, and "m68k is rumored to work on some platforms" and "VAX may also work" (according to Mike Stump). It still doesn't work on HP-PA or MIPS platforms.

Exception handling adds space overhead (the size of the executable grows); the problem is worse on the ix86 (Intel-like) architecture than on RISC architectures. The extra exceptions code is generated in a separate program section and is only paged in if an exception is thrown, so the cost is in disk, not in RAM or CPU.

Exception overhead is much lower on ix86 if you use binutils 2.9 or later, as gas (the GNU assembler) can now compress the information.

## Does g++ support namespaces?

As of version 2.7.2, g++ recognizes the keywords `namespace` and `using`, and there is some rudimentary code present, but almost nothing connected with namespaces works yet. The new versions (2.8.x/egcs) still lack namespace support, but to help compile standard programs they make

    using namespace std;

a no-op. There is namespace implementation work going on in the egcs snapshots (but it hasn't been released yet).

## What are the differences between g++ and the ARM specification of C++?

Up until recently, there was no really usable exception support. If you need exceptions, you want gcc-2.8.x or egcs. The implementation works fairly well. The 2.7.x version was strictly alpha quality and quite fragile.

Some features that the ANSI/ISO standardization committee has voted in that don't appear in the ARM are supported, notably the `mutable` keyword, in version 2.5.x. 2.6.x added support for the built-in boolean type `bool`, with constants `true` and `false`. Run-time type identification was rudimentary in 2.7.x but is fully supported in 2.8.x, so there are more reserved words: `typeid`, `static_cast`, `reinterpret_cast`, `const_cast`, and `dynamic_cast`.

As with any beta-test compiler, there are bugs. You can help improve the compiler by submitting detailed bug reports.

[ This paragraph obsoleted by 2.8.x/egcs: ] One of the weakest areas of g++ other than templates is the resolution of overloaded functions and operators in complex cases. The usual symptom is that in a case where the ARM says that it is ambiguous which function should be chosen, g++ chooses one (often the first one declared). This is usually not a problem when porting C++ code from other compilers to g++, but shows up as errors when code developed under g++ is ported to other compilers. (I believe this is no longer a significant problem in 2.7.0 or later).

[A full bug list would be very long indeed, so I won't put one here; the sheer complexity of the C++ language means that every compiler I've tried has some problems. 2.8.x and egcs are a big improvement]

## Will g++ compile InterViews? The NIH class library? Rogue Wave?

The NIH class library uses a non-portable, compiler-dependent hack to initialize itself, which makes life difficult for g++ users. It will not work without modification, and I don't know what modifications are required or whether anyone has done them successfully.

In short, it's not going to happen any time soon (previous FAQs referred to patches that a new NIHCL release would hopefully contain, but this hasn't happened).

Note: I thought I saw an item indicating that someone had patched NIHCL to work with g++. Any pointers?

I think that as of version 2.5.6, the standard g++ will compile the standard 3.1 InterViews completely successfully. Note that you'll need the `-fno-for-scope` flag if you use gcc-2.7.0; with 2.7.2 you may be able to omit this flag but you'll get warnings.

According to Jason Merrill, gcc-2.7.0 and newer works with Rogue Wave's `tools.h++` class library, but you may want to grab ``ftp://ftp.cygnus.com/pub/g++/Tools.h++-6.1-patch'`. Again, you'll need the `-fno-for-scope` flag since Rogue Wave hasn't fixed their code to comply with the new standard yet.

## Debugging on SVR4 systems

"How do I get debugging to work on my System V Release 4 system?"

Most systems based on System V Release 4 (except Solaris) encode symbolic debugging information in a format known as `DWARF'. There are two forms of DWARF, DWARF 1 and DWARF 2. The default is often DWARF 1, which is not really expressive enough to do C++ correctly.

Now that we have gdb 4.17, DWARF debugging is finally supported (if you use gcc 2.8.1 or egcs-1.0.x or newer).

For users of older versions of the tools, you can get g++ debugging under SVR4 systems by configuring gcc with the `--with-stabs` option. This causes gcc to use an alternate debugging format, one more like that used under SunOS4. You won't need to do anything special to GDB; it will always understand the "stabs" format.

To specify DWARF 2 output on Unixware, you can give the `-ggdb` switch; alternatively, `-gstabs` produces "stabs" format.

## debugging problems on Solaris

"I'm on Solaris, and gdb says it doesn't know about some of my local symbols. Help!"

This problem was introduced in gcc 2.7.2; debug symbols for locals that aren't declared at the beginning of a block come out in the wrong order, and gdb can't find such symbols.

This problem is fixed in gcc-2.7.2.1.

## X11 conflicts with libg++ in definition of String

"X11 and Motif define String, and this conflicts with the String class in libg++. How can I use both together?"

One possible method is the following:

    #define String XString
    #include <X11/Intrinsic.h>
    /* include other X11 and Motif headers */
    #undef String

and remember to use the correct `String` or `XString` when you declare things later.

## Why can't I assign one stream to another?

[ Thanks to Per Bothner and Jerry Schwarz for this section. ]

Assigning one stream to another seems like a reasonable thing to do, but it's a bad idea. Usually, this comes up because people want to assign to `cout`. This is poor style, especially for libraries, and is contrary to good object-oriented design. (Libraries that write directly to `cout` are less flexible, modular, and object-oriented).

The iostream classes do not allow assigning to arbitrary streams, because this can violate typing:

    ifstream foo ("foo");
    istrstream str(...);
    foo = str;
    foo->close ();  /* Oops! Not defined for istrstream! */

The original cfront implementation of iostreams by Jerry Schwarz allows you to assign to `cin`, `cout`, `cerr`, and `clog`, but this is not part of the draft standard for iostreams and generally isn't considered a good idea, so standard-conforming code shouldn't use this technique.

The GNU implementation of iostream did not support assigning to `cin`, `cout`, `cerr`, and `clog` for quite a while, but it now does, for backward compatibility with cfront iostream (versions 2.6.1 and later of libg++).

The ANSI/ISO C++ Working Paper does provide ways of changing the streambuf associated with a stream. Assignment isn't allowed; there is an explicit named member that must be used.

However, it is not wise to do this, and the results are confusing. For example: `fstream::rdbuf` is supposed to return the original filebuf, not the one you assigned. (This is not yet implemented in GNU iostream.) This must be so because `fstream::rdbuf` is defined to return a `filebuf *`.

Go to the first, previous, next, last section, table of contents.