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

# User Problems

- missing virtual table: Linker complains about missing virtual table
- for scope: gcc-2.7.0 breaks declarations in "for" statements!
- const constructor: g++ seems to want a const constructor. What's that?
- unused parameter warnings: How to silence "unused parameter" warnings
- jump crosses initialization: g++ objects to a declaration in a case statement
- Demangler: Where can I find a demangler?
- static data members: Linker reports undefined symbols for static data members
- internal compiler error: What does "internal compiler error" mean?
- bug reports: I think I have found a bug in g++.
- porting to g++: Porting programs from other compilers to g++
- name mangling: Why does g++ mangle names differently from other C++ compilers?
- problems linking with other libraries: Why can't g++ code link with code from other C++ compilers?
- documentation: What documentation exists for g++ 2.x?
- templates: Problems with the template implementation
- undefined templates: I get undefined symbols when using templates
- redundant templates: I get multiply defined symbols when using templates
- Standard Template Library: Does g++ support the Standard Template Library?
- STL and string: I'm having problems mixing STL and <string>.
- exceptions: Problems and limitations with exceptions
- namespaces: Does g++ support namespaces?
- agreement with standards: What are the differences between g++ and the ARM specification of C++?
- compiling standard libraries: Will g++ compile InterViews? NIHCL? Rogue Wave?
- debugging on SVR4 systems: Debugging on SVR4 systems
- debugging problems on Solaris: debugging problems on Solaris
- X11 conflicts with libg++: Conflict over meaning of String
- assignment to streams: Why can't I assign one stream to another?

## 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 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.

## 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 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).

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.6.3, there are still a few limitations in the template implementation besides the above (thanks to Jason Merrill for this info): These are still present in version 2.7.2, but a new implementation of templates planned for version 2.8 will eliminate them.

1. Static data member templates are not supported. 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)

   (still a limitation in 2.7.2)
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: 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 and later is to specify

       extern template int min (int, int);

   before `f()`; this will force it to be instantiated (though not emitted).
4. Member function templates are always instantiated when their containing class is. This is wrong.

## 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?

The Standard Template Library (STL) uses many of the extensions that the ANSI/ISO committee has made to templates, and g++ doesn't support some of these yet. So if you grab HP's free implementation of STL it isn't going to work. However, starting with libg++-2.6.2 libg++ contains a hacked version of STL, based on work by Carsten Bormann, which permits g++ to compile at least the containers (thanks to Per Bothner for this text).

Actually, as of libg++ version 2.7.2 most of this works quite well, most of the time; I've succeeded in making significant use of it. Almost all of the ObjectSpace examples (a set of over 200 simple examples of STL usage) now work.

When version 2.8.0 is out (with its complete redesign of the template implementation) a much more complete implementation of the STL (based on a newer free implementation from SGI) will be included.

There are several commercial suppliers of STL implementations; ObjectSpace's version supports gcc-2.7.x.

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 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.

## Problems and limitations with exceptions

Recent g++ versions provide limited support for exceptions. You must provide the `-fhandle-exceptions` flag to enable exception handling. As of version 2.7.2, exceptions may not work properly (and you may get odd error messages when compiling) if you turn on optimization (the `-O` flag).

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.

## 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. It appears that this will still be true when 2.8.0 is released.

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

As of version 2.7.0, g++ has exception support on most but not all platforms (no support on MIPS-based platforms yet), but it doesn't work right if optimizaton is enabled, which means the exception implementation is still not really ready for production use.

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 adds support for the built-in boolean type `bool`, with constants `true` and `false`. The beginnings of run-time type identification are present, 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.

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).

[A full bug list would be very long indeed, so I won't put one here. I may add a list of frequently-reported bugs and "non-bugs" like the static class members issue mentioned above].

## 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'.

Although the GNU C compiler already knows how to write out symbolic debugging information in the DWARF format, the GNU C++ compiler does not yet have this feature yet. However, work is in progress for DWARF 2 debug support for gcc and g++ and will be available in a future release (probably 2.8.0).

In the meantime, 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.

## 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.