Go to the first, previous, next, last section, table of contents.
"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 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.
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.
"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; }
"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; }
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).
"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.
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++, 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.
"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).
See the answer to the next question.
"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.
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:
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.
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)
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
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.
(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.
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.
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'
[ 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.
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.
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).
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]
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.
"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.
"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 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.
[ 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.