Versions, Patches, and SupportQ:
How can I dependably identify the C++ compiler in each new release?
A:
Every compiler predefines some macros that identify it. Compiler vendors tend to keep these predefined macros stable from release to release, and we in particular document them as a stable public interface. A good way to find out what compiler you have is to write a small program that tests for predefined macros and outputs a string suitable for your intended use. You can also write a pseudo-program and compile it with -E (or the equivalent for other compilers). See 'macros' in the index of the C++ User's Guide for a list of predefined C++ compiler macros. In particular, the value of __SUNPRO_CC, which is a three-digit hex number. The first digit is the major release. The second digit is the minor release. The third digit is the micro release. For example, C++ 5.6 is 0x560. Here are predefined macros of interest:
Q:
What is the difference between standard and classic I/O streams? Can you recommend text books on the subject?
A:
The design and implementation of the two libraries are entirely different. The programming interface for simple I/O is quite similar. For more complex operations, such as writing your own stream classes or manipulators, it is quite different.
The classic iostream library in this version is compatible with the version shipped with C++ 3.x and 4.x. In addition to the documentation provided with this release, here is a reference book:
For example, the following code works with both classic and standard iostreams using our compiler, although not with all compilers: #include <iostream.h> class myclass { public: myclass(int i) : k(i) { } friend ostream& operator<<(ostream&, const myclass&); private: int k; }; // user-written output operator ostream& operator<<(ostream& os, const myclass& m) { os << m.k; return os; } int main() { // simple I/O using cout, cin cout << "Enter a number: " << endl; int val; if( ! (cin >> val) ) { cout << "Invalid entry, using zero" << endl; val = 0; } // using the user-written output operator myclass m(val); cout << "Value is " << m << endl; } This code compiles and runs using Sun compilers in any of these ways: example% CC example.cc # standard mode with standard iostreams example% CC -library=iostream example.cc # standard mode with classic iostreams example% CC -compat=4 example.cc # C++ 4.2 compatbility mode Q:
How can I tell which C++ compiler versions are compatible?
A:
First, a definition: "Upward compatible" means that object code
compiled with an older compiler can be linked with code from a
later compiler, as long as the compiler that is used in the final
link is the latest compiler in the mix.
The C++ 4.0, 4.1, and 4.2 compilers are upward compatible.
(There are some "name mangling" issues among the compiler versions
that are documented in the C++ 4.2 manuals.)
The C++ versions 5.0 through 5.6 compilers in compatibility mode (-compat) are upward compatible with the 4.2 compiler. The actual object code from C++ 4.2 and versions 5.0 through 5.6 is fully compatible, but debugging information (stabs) emitted by later compilers is not compatible with earlier debuggers. Since the C++ version 5.0 compiler in default standard mode are upward compatible. The actual object code is fully compatible, but debugging information (stabs) emitted by later compilers is not compatible with earlier debuggers. Q:
What RogueWave libraries are "certified" for use with Sun Studio software?
A:
We cannot reliably track which vendors have certified which versions of their products for use with which versions of our compilers. And making sure this FAQ is always up to date would be harder still. You have to check with the vendor to find out whether they have tested their product with any particular version of the C++ compiler.
However, some RogueWave libraries ship with our compilers, and we implicitly certify that the versions we ship work together.
Q:
How can I figure out which patches exist and what problems are solved in the current patches?
A:
For the most up-to-date information on product patches, check the Developer's Portal.
Product patches can be downloaded from SunSolve. Q:
Do I need to have patches to libC.so.5 and libCrun.so.1?
A:
Typically, the Solaris operating system ships with the most recent versions of these libraries. However, due to bug fixes and some performance improvements, there are often patches to these libraries. These patches are always cumulative and always backward compatible, so it is a good idea to pick up the latest patch available from Sun Solve. The following table shows the current matrix of patch IDs. Please check for the latest package in the database. The package is called SUNWlibC (32bit) and SUNWlibCx(64bit). Use the Advanced Search page and look for libCrun. Be sure to limit the search to 'Patch Descriptions' instead of 'All Support Resources' which is the default. >> See Patch Table.Compiler CompatibilityQ:
I recently patched my Solaris Operating System and now my code won't compile. What happened?
A:
New math functions available in recent Solaris versions can cause previously valid code to become invalid.
The functions in <math.h> previously had versions only for type double. The new Solaris headers and library have overloads for types float and long double as well. To avoid an ambiguous call you might need to add explicit casts when calling these functions with integer arguments. For example:
#include <math.h> The Solaris patches listed below provide full ANSI C++ <cmath> and <math.h> library support as implemented in the libm patch for Solaris 8 and 9.
Q:
Can I mix compatibility mode (-compat) code with standard mode code?
A:
We recommend against, and do not support, mixing code in the same program, even through "plug-ins" or dynamically-loaded libraries for the following reasons:
Q:
How do I mix C++ or C programs with F77, F90, or F95 programs?
A:
Starting with Sun Workshop 6 update 1 (compiler version 5.2), you can use the -xlang={f90|f95|f77} option. This option tells the driver to figure out exactly which libraries need to be on the link line and to figure out the order in which they need to appear.
The -xlang option is not available for the C compiler. To mix C and Fortran routines, you must compile them with cc and link them using the Fortran linker.
Coding and DiagnosticsQ:
Why do I get errors and warnings involving file foo.cc when I'm not compiling or including foo.cc in my program?
A:
If a header file foo.h has template declarations, the compiler by default searches for a file foo with a C++ file extension (foo.c, foo.cc, foo.C, foo.cpp, foo.c++) and includes it automatically if it is found. Refer to the C++ User's Guide section titled "Template Definitions earching" for details. If you have a file foo.cc that you don't intend to be treated this way, you have two options:
Refer to the C++ User's Guide sections 5.2.1 and 5.2.2 for further discussion of the template definitions model or refer to the index of the C++ User's Guide for pointers to descriptions of the definitions separate and definitions included models. Q:
Why do I get "duplicate definition" error messages when I compile the foo.i file that is generated from the -P preprocessing option?
A:
By default, the compiler allows template definitions to be separate from their declarations. Refer to the C++ User's Guide sections 5.2.1 and 5.2.2 for further discussion of the template definitions model or refer to the index of the C++ User's Guide for pointers to descriptions of the definitions separate and definitions included models. When the compiler sees a declaration without a definition of a needed template in a .h or .i file, it looks for a template definition file. A file with the same name as the .h or .i file but with one of the extensions c, cc, C, c++, or cpp, is assumed to have template definitions. If such a file exists, it is included automatically, as documented in the C++ manual. Suppose file foo.cc is compiled with -P, thus generating foo.i, and has a declaration for a needed template but no definition. The compiler looks for a definition file and finds foo.cc. The foo.cc file gets included automatically, which results in duplicate definitions. You can turn off the compiler's search for template definitions by specifying the -template=no%extdef option. However, that option disables all searches for separate template definitions. The C++ standard library implementation relies on the compiler finding the separate definitions. For this case, where you want to compile a .i file, just rename the file, giving it a unique name. Then you don't have to disable separate template compilation. For example: CC -P foo.ccmv foo.i foo_prep.i CC -c foo_prep.i Note that this will not work if you use the -E option to generate pre-processed files. The -E option keeps a record of the included file names, so a .cc file can still be found automatically. Q:
Why am I getting an error when I link a SPARC V9 archive library into a dynamic library? It worked in Sun Studio 8.
A:
The new, default, compiler-address code-model for V9 is
-xcode=abs44, which improves performance over the previous
-xcode=abs64. However, the new code model is not usable
within dynamic libraries. There are two solutions to the
problem.
Q:
What causes this message: "SunWS_cache: Error: Lock attempt failed for SunWS_cache"?
A:
There are two main causes for the "lock attempt failed" error message about the template cache:
Q:
Why do I get the following warning from the linker: "ld: warning: symbol 'clog' has differing types"?
A:
The linker warns about the pair of weak symbols that have different types when you link libm.so.2 and the classic iostream library in the same program. You can ignore the warning. The default math library on Solaris 10 is libm.so.2 and it contains the complex log function 'clog' in the global namespace as required by the C99 standard. If you use C++ classic iostreams by specifying -compat=4 or by specifying -library=iostream, you get the buffered standard error stream 'clog' in the global namespace. (Standard iostreams does not have this conflicting symbol.) We have adjusted headers and libraries to silently rename each of these 'clog' symbols so that you can use both in one program. However, we must retain the original symbol spellings as weak symbols in each of the libraries, so that old binaries looking for the original symbols can continue to link. Be sure to get iostream and math declarations by including the appropriate system headers rather than declaring any of these entities yourself. Q:
Why does my multi-threaded program using STLport crash when I compile it with -xarch=v8plus or -xarch=v8plusa?
A:
STLport originally had a bug that prevented correct
multi-threaded operation when compiling with -xarch=v8plus or
-xarch=v8plusa. The bug was fixed, but the fix involved a
change in the STLport headers, and a change in some STLport
objects. Code compiled using earlier versions of the STLport
headers needs to be recompiled with C++ 5.6 or with a patched
earlier release before being linked into new programs.
Q:
Why does the compiler now say that a call to abs() is ambiguous?
A:
The C++ Standard in section 26.5 requires the following
overloads of the abs function:
Until fairly recently, the only version of abs available on Solaris was the traditional int version. If you invoked abs with any numeric type, the value was implicitly converted to type int, and the int version of abs was called, assuming that you included <stdlib.h> or <cstdlib>. Recent updates of Solaris headers and libraries now comply with the C++ standard regarding math functions. If you include, for example, <math.h> but not < stdlib.h>, and invoke abs with an integer argument, the compiler must choose among the three floating-point versions of the functions. An integer value can be converted to any of the floating-point types, and neither conversion is preferred over the others. Reference: C++ standard section 13.3.3. The function call is therefore ambiguous. You will get an ambiguity error using any compiler that conforms to the C++ Standard. If you invoke the abs function with integer arguments, you should include standard header <stdlib.h> or <cstdlib> to be sure you get the correct declarations for it. If you invoke abs with floating-point values, you should also include <math.h> or <cmath>. Here's a simple recommended programming practice: if you include <math.h> or <cmath>, also include <stdlib.h> or <cstdlib>. Similar considerations apply to other math functions, like cos or sqrt. Solaris headers and libraries now comply with the C++ Standard, supplying float, double, and long double overloaded versions of the functions. If you invoke, for example, sqrt with an integer value, the code formerly compiled because only one version of sqrt was available. With three floating-point versions available, you must cast the integer value to the floating-point type that you want.
double root_2 = sqrt(2); // error Q:
When do temporary objects get destroyed?
A:
The compiler creates a temporary object sometimes for convenience, and sometimes because the language rules require it. For example, a value returned by a function is a temporary object, and the result of a type conversion is a temporary object. The original C++ rule was that the temporary object ("temp") could be destroyed at any time up until the end of the block in which it was created. Sun C++ compilers destroyed temps at the end of the block (closing right brace). After much debate over several years, the C++ Committee settled on a fixed place where temps should be destroyed: at the end of the complete expression in which the temp is created. Usually that is at the end of the statement in which the expression appears. That is the rule in the C++ Standard. We found that many programs using Sun C++ depended (perhaps unintentionally) on temps living until the end of the block. Accordingly, we left the compiler default behavior unchanged: Temporary objects by default are destroyed at the end of the block in which they are created. If you want standard-conforming behavior, where temps are destroyed at the end of the complete expression in which they are created, use the compile-time option -features=tmplife. You do not need to use the option consistently throughout a program. Temporary objects created in a module will be destroyed at the end of the expression or the end of the block in that module depending on the option in effect at compilation time. Q:
Why does the compiler report an ambiguity for the standard exception class?
A:
On Solaris, standard header <math.h> has a declaration for a struct "exception", as required by standard Unix. If you bring the C++ standard exception class into global scope with a using-declaration or using-directive, it creates a conflict.
// Example 1 #include <math.h> #include <exception> using namespace std; // using-declaration exception E; // error, exception is ambiguous // Example 2: #include <math.h> #include <exception> using std::exception; // using-directive exception E; // error, multiple declaration for exception Name resolution is slightly different for using-declarations compared to using-directives, so the error messages are not quite the same. Workarounds:
Q:
Why does C++ 5.3 emit errors about throw specifications on my derived virtual functions?
A:
A C++ rule newly enforced by the 5.3 C++ compiler is that a virtual function in a derived class can allow only the exceptions that are allowed by the function it overrides. The overriding function can be more restrictive, but not less restrictive. Consider the following example:
class Base { public: // might throw an int exception, but no others virtual void f() throw(int); }; class Der1 : public Base { public: virtual void f() throw(int); // ok, same specification }; class Der2 : public Base { public: virtual void f() throw(); // ok, more restrictive }; class Der3 : public Base { public: virtual void f() throw(int, long); // error, can't allow long }; class Der4 : public Base { public: virtual void f() throw(char*); // error, can't allow char* }; class Der5 : public Base { public: virtual void f(); // error, allows any exception }; This code shows the reason for the C++ rule: #include "base.h" // declares class Base void foo(Base* bp) throw() { try { bp->f(); } catch(int) { } } Since Base::f() is declared to throw only an int exception, function foo can catch int exceptions, and declare that it allows no exceptions to escape. Suppose someone later declared class Der5, where the overriding function could throw any exception, and passed a Der5 pointer to foo. Function foo would become invalid, even though nothing is wrong with the code visible when function foo is compiled. Q:
Why do template instances turn up missing when I link my program? The instances seem to be in the template cache.
A:
Starting with C++ 5.5, the compiler does not use a template cache by default. Therefore we recommend that when you upgrade to C++ 5.5 or newer, you recompile your code by specifying -instances=global in order to use the default template compilation model. The template cache maintains a list of dependencies between the object files that the compiler generates, and the template instances in the cache. Note, however, that the compiler now only uses the template cache when you specify -instances=extern. If you move or rename object files, or combine object files into a library, you lose the connection to the cache. Here are two alternatives:
Q:
Why do I get a warning about a function not being expanded when I use +w2 and not when I use +w2 +d?
A:
The C++ compiler has two kinds of inlining: C++ inline function inlining, which is done by the parser, and optimization inlining, which is done by the code generator. The C and Fortran compilers have only optimization inlining. (The same code generator is used for all compilers on a platform.)
The C++ compiler's parser attempts to expand inline any function that is declared implicitly or explicitly as inline. If the function is too large, the parser emits a warning only when you use the +w2 option. The +d option prevents the parser from attempting to inline any function. This is why the warning disappears when you use +d. (The -g option also turns off the inlining of C++ inline functions.) The -xO options do not affect this type of inlining.
The optimization inlining does not depend on the programming language. When you select an optimization level of -xO4 or higher, the code generator examines all functions, independent of how they were declared in source code, and replaces function calls with inline code wherever it thinks the replacement will be beneficial. No messages are emitted about optimization inlining (or its failure to inline functions). The +d option does not affect optimization inlining.
Q:
Can I use the -ptr option to have multiple template repositories, or to share repositories among different projects? If not, what can I do?
A:
The -ptr option is not supported in versions 5.0 through 5.6. Although it was available in version 4.2, it did not always work as users expected, and it caused many problems. The best advice is not to share repositories among different projects. The sharing of repositories is likely to cause problems more severe than the problem you are trying to solve. Compile only one project in any one directory. Use a different directory for the binaries associated with a different project. Beginning with version 5.0, the compiler puts a template repository in the same directory as the object file being generated. If you want to use multiple repositories for one project, generate an object file in the directory where you want the associated repository to be. At link time, all the repositories associated with the object files will automatically be searched for template instances. No compiler options are required. Q:
Why does fprintf("%s",NULL) cause a segmentation fault?
A:
Some applications erroneously assume that a null character pointer should be treated the same as a pointer to a null string. A segmentation violation occurs in these applications when a null character pointer is accessed.
There are several reasons for not having the *printf() family of functions check for null pointers. These include, but are not limited to the following reasons:
Q:
Depending on how I call sqrt(), I get different signs for the imaginary part of the square root of a complex number. What's the reason for this?
A:
The implementation of this function is aligned with the C99 csqrt Annex G specification. For example, here's the output from the following code example:
complex sqrt (3.87267e-17, 0.632456)
float sqrt (3.87267e-17, -0.632456)
Q:
A friend function in a class template does not get instantiated and I get link-time errors. This worked with C++ 5.0, why doesn't it work now?
A:
The following test case compiles and links without errors with the C++ 5.0 compiler but causes link-time errors with later versions of the compiler:
example% cat t.c
#include <ostream>
using std::ostream;
template <class T>
class TList { public: friend ostream& operator<< (ostream&, const TList&); }; template <class T> ostream& operator<< (ostream& os, const TList<T>& l) { return os; } class OrderedEntityList { public: TList<int> *Items; ostream& Print(ostream &) const; }; ostream& OrderedEntityList::Print(ostream& os) const { os << *Items; return os; } main() { } example% CC t.c Undefined first referenced symbol in file std::basic_ostream<char,std::char_traits<char> >&operator<<(std::basic_ostream<char,std::char_traits<char< <&,const TList<int>&) 4421826.o ld: fatal: Symbol referencing errors. No output written to a.out The test case is invalid according to the standard. The problem is that the declaration friend ostream& operator<< (ostream&, const TList&); does not refer to any template instance. The unqualified name lookup cannot match a template declaration even if one were visible at the point of the friend declaration. To get the friend declaration to match a template, you need either to declare it as a template function, or qualify the name. Either way, the declaration for the template must be visible at the point of the friend declaration. To summarize, the friend declaration does not refer to a template, but it declares a function that is the best match to the function call. (A non-template function is preferred over a template function if they are otherwise equal.) The following code is valid: template <class T> class TList; // so we can declare the operator<< template template <class T> ostream& operator<< (ostream& os, const TList<T>& l) { return os; } template <class T> class TList { public : // note the scope qualification on the function name friend ostream& ::operator<< (ostream&, const TList&); }; Q:
Why does the compiler say a member of an enclosing class is not accessible from a nested class?
A:
class Outer {
According to the ARM and to the C++ Standard, a nested class has no special access to members of the enclosing class. Since my_int and k are private in Outer, only friends of Outer have access to them. In order to make a nested class a friend, you must first forward-declare the class, then make it a friend, as the following example shows: class Outer {
class Inner; friend class Inner; class Inner { my_int j; // OK int foo() { return k; // OK } }; }; Q:
What causes the "pure virtual function call" message at run time?
A:
A "pure virtual function called" message always arises because of an error in the program. The error occurs in either of the following two ways:
Q:
Why does the compiler say that a derived-class virtual function hides a base-class virtual function with a different signature? My other compiler doesn't complain about the code.
A:
The C++ rule is that overloading occurs only within one scope, never across scopes. A base class is considered to be in a scope that surrounds the scope of a derived class. Any name declared in a derived class therefore hides, and cannot overload, any function in a base class. This fundamental C++ rule predates the ARM.
If another compiler does not complain, it is doing you a disservice, because the code will not behave as you probably expect. Our compiler issues a warning while accepting the code. (The code is legal, but probably does not do what you want.)
If you wish to include base-class functions in an overloaded set, you must do something to bring the base-class functions into the current scope. If you are compiling in default standard mode, you can add a using-declaration:
class Base { Library CompatibilityQ:
What library configuration macros can I modify to get different features from the C++ compiler runtime libraries?
A:
Do not attempt to define, undefine, or modify any of the library configuration macros. The library headers must match the way the libraries were built. Otherwise, your program might not compile, might not link, and probably will not run correctly.
Q:
When do I need to use -I and -L options?
A:
Specify the -I option to point to directories that contain your project header files when these header files are not in the same directory as the files that include them, or to point to directories that contain header files for third-party libraries that you acquire. Specify the -L options to point to directories that contain libraries that you build, or to third-party libraries that you acquire.
Never use -I to point into /usr/include or into the compiler installation area. Never use -L to point into /lib, /usr/lib, or into the compiler installation area. The CC compiler driver knows the location of the system headers and libraries and follows the correct search order. You can cause the compiler to find the wrong headers or libraries by using -I or -L options that point into system directories. Q:
How do I get a C++ standard library (stdlib) that is fully compliant? What functionality does the current libCstd not support?
A:
This release includes STLport's Standard Library implementation version 4.5.3 as an optional standard library. STLport has good conformance to the C++ standard, and also has some popular extensions. However, it is not binary compatible with the standard library that is used by default.
The current libCstd was developed for version 5.0 of the C++ compiler. That version did not support templates as members of classes. Some parts of the standard library require member templates, meaning that some functionality is missing. The missing functionality mostly shows up in container classes that have constructor templates allowing implicit type conversions. You have to write explicit conversions in your source code as a workaround.
Beginning with version 5.1, the C++ compiler supports templates as members of classes, and can support a standard-conforming library. We cannot update the library without breaking source and binary compatibility, so we continue to ship a libCstd with the same limitations.
You can find public implementations of standard libraries at gnu and SGI web sites, and you can also purchase libraries from vendors such as RogueWave and Dinkumware. See also the following question about the STL.
Q:
I need the C++ standard template library (STL). Where do I get it? Is there one for compatibility mode (-compat)?
A:
The C++ compiler now supports STLport's Standard Library implementation version 4.5.3. libCstd is still the default library, but STLport's product is now available as an alternative. This release includes both a static archive called libstlport.a and a dynamic library called libstlport.so.
Issue the following compiler option to turn off libCstd and use STLport:
-library=stlport4 Both the default C++ standard library libCstd as well as STLport contain the STL. You can use a different version of the standard library, but doing so is risky and good results are not guaranteed. To plug in a different STL, use the -library=no%Cstd option and point the compiler to your header files and library of choice. If the replacement library does not have its own iostreams library, and if you can use "classic" iostreams instead of standard iostreams, add -library=iostream to the command line. For detailed instructions, see "Replacing the C++ Standard Library" in the C++ User's Guide that ships with the compiler. This guide is available online. Q:
What standard library functionality is missing from libCstd?
A:
The standard library was originally (in C++ 5.0) built without support for features which required member template and partial specialization in the compiler. Although these features have been available since C++ 5.1, they cannot be turned on in the standard library because they would compromise backward compatibility. The following is a list of missing functionality for each disabled feature.
Disabled feature: member template functions
Disabled feature: member template classes
Disabled feature: overloading of function template arguments that are partial specializations
Disabled feature: partial specialization of template classes with default parameters
Q:
What are the consequences of the missing standard library functionality?
A:
Some code that is valid according to the C++ standard will not compile. The most common example is creating maps where the first element of the pair could beconst but isn't declared that way.
The member constructor template would convert pair<T,
U> to pair<const T, U> implicitly when
needed. Because that constructor is missing, you get compilation
errors instead.
Since you are not allowed to change the first member of a pair
in a map anyway, the simplest fix is to use an explicit Q:
Is there a version of tools7 library that works with standard streams? Will there be a tools8 available soon?
A:
Yes there is, but only with C++ 5.3, 5.4, 5.5, and 5.6. Use
the -library=rwtools7_std command to compile and link with
this library.
RogueWave has changed the way Tools.h++ works, and now supplies it only as part of their SourcePro product. There is no Tools.h++ version 8, as such. Compile-Time PerformanceQ:
I recently upgraded to the Sun Open Network Environment (Sun ONE) Studio 8 C++ 5.5 compiler and noticed a significant increase in link-time during compilation. Why did this happen and is there a workaround?
A:
There are two probable causes for a dramatic increase in link-time. The most likely cause is a change in the way the compiler generates inline functions out of line. The compiler generates an inline function as an ordinary callable function (out of line) when any of the following is true:
Prior to the Sun ONE Studio 8 C++ 5.5 compiler, the compiler created a local (non-external) copy of a function in each module that needed it when an inline function was generated out of line. This was problematic because it caused code bloat, but more importantly, it violated the C++ standard. The C++ standard requires that only one copy of a non-static inline function appear in the final program. If you take the address of an inline function, it must be generated out of line. If you take the address in two different modules, the addresses would be different, which could affect program behavior. Starting with the Sun ONE Studio 8 C++ 5.5 compiler, the compiler generates out-of-line inline functions as global functions in a comdat section, the same way it generates template instances by default. The advantages of this change are that the final program is smaller, and the program meets the requirements of the C++ standard. The disadvantage is that the linker has more work to do when the program has many out-of-line inline functions. The linker must process these functions as external symbols, when previously they were invisible, and it must discard the duplicates. You can restore the previous compiler behavior regarding inline functions by specifying -features=no%extinl. If this change solves the problem, then you can choose between a smaller program or faster link time (assuming you don't care about multiple copies of inline functions.) The second, and less likely, cause of increased link-time relates to whether your program generates a large number of template instances. It is possible that the change in template handling beginning with version 5.5 of the C++ compiler causes longer link times. It is almost always faster for both compiling and linking to create global comdat instances of templates in each .o file directly instead of keeping a single copy in the template cache. However, a program that uses the same few template instances in many different modules might link faster using the template cache. If your program uses a lot of templates, and reverting to the old model of inline functions did not account for the difference in link time, try re-building and using the option -instances=extern. This option was the default prior to C++ 5.5. Q:
How come I'm not seeing an improvement in compile time even though I've started using the precompiled header facility of the C++ compiler?
A:
Using precompiled headers does not guarantee faster compile
times. Precompiled headers impose some overhead that is not
present when you compile files directly. To gain a
performance advantage, the precompiled headers must have some
redundancy that precompilation can eliminate.
For example, a program that is highly likely to benefit from precompilation is one that includes many system headers, iostreams, STL headers, and project headers. Those files contain conditionally-compiled code. Some headers are included multiple times, and the compiler must scan over the entire file if only to discover there is nothing to do in the redundant includes. System headers typically have hundreds of macros to expand. Using a precompiled header means opening one file instead of dozens. The multiple includes that do nothing are eliminated, as are comments and extra white space. The macros in the headers are pre-expanded. Typically, these savings add up to a significant reduction in compile time. Q:
Why does a large file take so much longer to compile than a shorter one?
A:
The size of the file is probably not the issue so here are three likely causes for the delay.
Q:
I have seen enormous compile times with compiler versions 5.0 and version 5.1 (compared to 4.2). Can I expect this problem to be fixed in the near future?
A:
We have improved compile times considerably in 5.1patch01 through the current version. If you are unhappy with the compiler's performance, keep the following recommendations in mind:
Q:
We have noticed much larger binaries compared to the 4.2 version of the compiler. Is there a solution to this?
A:
The binaries increase in size for -g compiles because, starting with version 5.0, the compiler generated lots of template debugging information . The 5.1 compiler greatly reduced the size of the generated debug information for many kinds of programs. The current compiler through version 5.2 have added further improvements. In many cases, the binary decreases from 25% to over 50% in size. The improvements show up mostly for code using namespaces, templates, and class hierarchies with many levels of inheritance.
Q:
Can a single compilation process be distributed onto multiple processors? More generally, does a multiprocessor (MP) system always have better compile-time performance?
A:
The compiler itself is not multithreaded. You can expect better performance with MP systems, because the computer always has many other processes running at the same time as any one compilation.
If you use dmake (one of the tools that ships with the compiler), you can run multiple compilations simultaneously.
Run-Time PerformanceQ:
Standard library streams are slower than gcc or KAI streams. This is a performance hit for me. Is there a solution in sight?
A:
You can either specify the new C++ compiler option -sync_stdio=no at link time to fix this problem or add a call
to the sync_with_stdio(false) function and recompile.
The major performance problem with stdlib 2.1.1 is that it synchronizes C stdio with C++ streams by default. Each output to cout is flushed immediately. If your program does a lot of output to cout but not to stdout, the excess buffer flushing can add significantly to the run-time performance of the program. The C++ standard requires this behavior, but not all implementations meet the standard. The following program demonstrates the synchronization problem. It must print "Hello beautiful world" followed by a newline: #include <iostream> #include <stdio.h> int main() { std::cout << "Hello "; printf("beautiful "); std::cout << "world"; printf("\n"); } If cout and stdout are independently buffered, the output could be scrambled. If you cannot recompile the executable, specify the new C++ compiler option -sync_stdio=no at link time. This option causes sync_with_stdio( ) to be called at program initialization before any program output can occur. If you can recompile, add a call to the sync_with_stdio(false) function before any program output thereby specifying that the output does not need to be synchronized. Here is a sample call: #include int main(int argc, char** argv) { std::ios::sync_with_stdio(false); } The call to sync_with_stdio should be the first one in your program. See the C++ User's Guide or the C++ man page CC(1) for more information on -sync_stdio. Q:
Does C++ always inline functions marked with "inline" keyword? Why didn't I see functions inlined even though I wrote them that way?
A:
Fundamentally, the compiler treats the inline declaration as
a guidance and attempts to inline the function. In compiler
versions 5.1 through 5.6, the inlining algorithm has been
revamped to make it understand more constructs. However,
there are still cases where it will not succeed. The
restrictions are:
|
| ||||||||||||||||||||||||||||||||||||||||||||||||||||
|
| ||||||||||||