"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; }
"I have a program that worked just fine with older g++ versions, but as of version 2.5.x it doesn't work anymore. Help!"
While it's always possible that a new bug has been introduced into the compiler, it's also possible that you have been relying on bugs in older versions of g++. For example, version 2.5.0 was the first version of g++ to correctly implement the "hiding rule." That is, if you have an overloaded function in a base class, and in a derived class you redefine one of the names, the other names are effectively "hidden". All the names from the baseclass need to be redefined in the derived class. See section 13.1 of the ARM: "A function member of a derived class is not in the same scope as a function member of the same name in a base class".
Here's an example that is handled incorrectly by g++ versions before 2.5.0 and correctly by newer versions:
class Base { public: void foo(int); }; class Derived : public Base { public: void foo(double); // note that Base::foo(int) is hidden }; main() { Derived d; d.foo(2); // Derived::foo(double), not Base::foo(int), is called }
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.
The libg++ distribution contains a version of etags that works for C++ code. Look in `libg++/utils'. It's not built by default when you install libg++, but you can cd to that directory and type
make etags
after you've installed libg++.
"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 defined 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.
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/~mrs/wp-draft.
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 these changes by FTP from ftp.std.com in `/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.
For versions 2.6.2 and later, the gcc/g++ distribution contains the gcc manual in PostScript. Also, Postscript versions of GNU documentation in U.S. letter format are available by anonymous FTP to primus.com in /pub/gnu-ps. The same, in A4 format, are on liasun3.epfl.ch in /pub/gnu/ps-doc.
A draft of a document describing the g++ internals appears in the gcc distribution (called g++int.texi); it is still incomplete.
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 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):
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.0)
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 and later is to specify
extern template int min (int, int);before
f()
; this will force it to be instantiated (though not
emitted).
(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.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.
From Per Bothner:
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, libg++-2.6.2 contains a hacked version of STL, based on work by Carsten Bormann, which permits gcc-2.6.3 to compile at least the containers. A full implementation is going to need improved template support, which will take a while yet.
As of libg++-2.7.0 and gcc-2.7.0, I've succeeded in making many short STL example programs work, though there are still a number of bugs and limitations.
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].
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).
[ From Steinar Bang <steinarb@idt.unit.no>]
InterViews 3.1 compiles and runs with gcc-2.3.3 and libg++-2.3, except that the "doc" application immediately dumps core when you try to run it. There is also a small glitch with idraw.
There is a patch for InterViews 3.1 from Johan Garpendahl <garp@isy.liu.se> available for FTP from site "ugle.unit.no". It is in the file
`/pub/X11/contrib/InterViews/g++/3.1-beta3-patch'.
This fixes two things: the Doc coredump, and the pattern menu of idraw. Read the instructions at the start of the file.
I think that as of version 2.5.6, the standard g++ will compile the standard 3.1 InterViews completely successfully. I'd appreciate a confirmation.
"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, nor is it likely to in the immediate future.
Ron Guilmette has done a great deal of work to try to get the GNU C++ compiler to produce DWARF format symbolic debugging information (for C++ code) but he gave up on the project because of a lack of funding and/or interest from the g++ user community. If you have a strong desire to see this project completed, contact Ron at <rfg@netcom.com>.
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.
"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.