| <chapter xmlns="http://docbook.org/ns/docbook" version="5.0" | |
| xml:id="std.support" xreflabel="Support"> | |
| <?dbhtml filename="support.html"?> | |
| <info><title> | |
| Support | |
| <indexterm><primary>Support</primary></indexterm> | |
| </title> | |
| <keywordset> | |
| <keyword>ISO C++</keyword> | |
| <keyword>library</keyword> | |
| </keywordset> | |
| </info> | |
| <para> | |
| This part deals with the functions called and objects created | |
| automatically during the course of a program's existence. | |
| </para> | |
| <para> | |
| While we can't reproduce the contents of the Standard here (you | |
| need to get your own copy from your nation's member body; see our | |
| homepage for help), we can mention a couple of changes in what | |
| kind of support a C++ program gets from the Standard Library. | |
| </para> | |
| <section xml:id="std.support.types" xreflabel="Types"><info><title>Types</title></info> | |
| <?dbhtml filename="fundamental_types.html"?> | |
| <section xml:id="std.support.types.fundamental" xreflabel="Fundamental Types"><info><title>Fundamental Types</title></info> | |
| <para> | |
| C++ has the following builtin types: | |
| </para> | |
| <itemizedlist> | |
| <listitem><para> | |
| char | |
| </para></listitem> | |
| <listitem><para> | |
| signed char | |
| </para></listitem> | |
| <listitem><para> | |
| unsigned char | |
| </para></listitem> | |
| <listitem><para> | |
| signed short | |
| </para></listitem> | |
| <listitem><para> | |
| signed int | |
| </para></listitem> | |
| <listitem><para> | |
| signed long | |
| </para></listitem> | |
| <listitem><para> | |
| unsigned short | |
| </para></listitem> | |
| <listitem><para> | |
| unsigned int | |
| </para></listitem> | |
| <listitem><para> | |
| unsigned long | |
| </para></listitem> | |
| <listitem><para> | |
| bool | |
| </para></listitem> | |
| <listitem><para> | |
| wchar_t | |
| </para></listitem> | |
| <listitem><para> | |
| float | |
| </para></listitem> | |
| <listitem><para> | |
| double | |
| </para></listitem> | |
| <listitem><para> | |
| long double | |
| </para></listitem> | |
| </itemizedlist> | |
| <para> | |
| These fundamental types are always available, without having to | |
| include a header file. These types are exactly the same in | |
| either C++ or in C. | |
| </para> | |
| <para> | |
| Specializing parts of the library on these types is prohibited: | |
| instead, use a POD. | |
| </para> | |
| </section> | |
| <section xml:id="std.support.types.numeric_limits" xreflabel="Numeric Properties"><info><title>Numeric Properties</title></info> | |
| <para> | |
| The header <filename class="headerfile"><limits></filename> defines | |
| traits classes to give access to various implementation | |
| defined-aspects of the fundamental types. The traits classes -- | |
| fourteen in total -- are all specializations of the class template | |
| <classname>numeric_limits</classname> | |
| and defined as follows: | |
| </para> | |
| <programlisting> | |
| template<typename T> | |
| struct class | |
| { | |
| static const bool is_specialized; | |
| static T max() throw(); | |
| static T min() throw(); | |
| static const int digits; | |
| static const int digits10; | |
| static const bool is_signed; | |
| static const bool is_integer; | |
| static const bool is_exact; | |
| static const int radix; | |
| static T epsilon() throw(); | |
| static T round_error() throw(); | |
| static const int min_exponent; | |
| static const int min_exponent10; | |
| static const int max_exponent; | |
| static const int max_exponent10; | |
| static const bool has_infinity; | |
| static const bool has_quiet_NaN; | |
| static const bool has_signaling_NaN; | |
| static const float_denorm_style has_denorm; | |
| static const bool has_denorm_loss; | |
| static T infinity() throw(); | |
| static T quiet_NaN() throw(); | |
| static T denorm_min() throw(); | |
| static const bool is_iec559; | |
| static const bool is_bounded; | |
| static const bool is_modulo; | |
| static const bool traps; | |
| static const bool tinyness_before; | |
| static const float_round_style round_style; | |
| }; | |
| </programlisting> | |
| </section> | |
| <section xml:id="std.support.types.null" xreflabel="NULL"><info><title>NULL</title></info> | |
| <para> | |
| The only change that might affect people is the type of | |
| <constant>NULL</constant>: while it is required to be a macro, | |
| the definition of that macro is <emphasis>not</emphasis> allowed | |
| to be an expression with pointer type such as | |
| <constant>(void*)0</constant>, which is often used in C. | |
| </para> | |
| <para> | |
| For <command>g++</command>, <constant>NULL</constant> is | |
| <code>#define</code>'d to be | |
| <constant>__null</constant>, a magic keyword extension of | |
| <command>g++</command> that is slightly safer than a plain integer. | |
| </para> | |
| <para> | |
| The biggest problem of #defining <constant>NULL</constant> to be | |
| something like <quote>0L</quote> is that the compiler will view | |
| that as a long integer before it views it as a pointer, so | |
| overloading won't do what you expect. It might not even have the | |
| same size as a pointer, so passing <constant>NULL</constant> to a | |
| varargs function where a pointer is expected might not even work | |
| correctly if <code>sizeof(NULL) < sizeof(void*)</code>. | |
| The G++ <constant>__null</constant> extension is defined so that | |
| <code>sizeof(__null) == sizeof(void*)</code> to avoid this problem. | |
| </para> | |
| <para> | |
| Scott Meyers explains this in more detail in his book | |
| <link xmlns:xlink="http://www.w3.org/1999/xlink" | |
| xlink:href="https://www.aristeia.com/books.html"><emphasis>Effective | |
| Modern C++</emphasis></link> and as a guideline to solve this problem | |
| recommends to not overload on pointer-vs-integer types to begin with. | |
| </para> | |
| <para> | |
| The C++ 2011 standard added the <constant>nullptr</constant> keyword, | |
| which is a null pointer constant of a special type, | |
| <classname>std::nullptr_t</classname>. Values of this type can be | |
| implicitly converted to <emphasis>any</emphasis> pointer type, | |
| and cannot convert to integer types or be deduced as an integer type. | |
| Unless you need to be compatible with C++98/C++03 or C you should prefer | |
| to use <constant>nullptr</constant> instead of <constant>NULL</constant>. | |
| </para> | |
| </section> | |
| </section> | |
| <section xml:id="std.support.memory" xreflabel="Dynamic Memory"><info><title>Dynamic Memory</title></info> | |
| <?dbhtml filename="dynamic_memory.html"?> | |
| <para> | |
| In C++98 there are six flavors each of <function>operator new</function> | |
| and <function>operator delete</function>, so make certain that you're | |
| using the right ones. | |
| Here are quickie descriptions of <function>operator new</function>: | |
| </para> | |
| <variablelist> | |
| <varlistentry> | |
| <term><code>void* operator new(std::size_t);</code></term> | |
| <listitem> | |
| Single object form. | |
| Throws <classname>std::bad_alloc</classname> on error. | |
| This is what most people are used to using. | |
| </listitem> | |
| </varlistentry> | |
| <varlistentry> | |
| <term><code>void* operator new(std::size_t, std::nothrow_t) noexcept;</code></term> | |
| <listitem> | |
| Single object <quote>nothrow</quote> form. | |
| Calls <code>operator new(std::size_t)</code> but if that throws, | |
| returns a null pointer instead. | |
| </listitem> | |
| </varlistentry> | |
| <varlistentry> | |
| <term><code>void* operator new[](std::size_t);</code></term> | |
| <listitem> | |
| Array <function>new</function>. | |
| Calls <code>operator new(std::size_t)</code> and so | |
| throws <classname>std::bad_alloc</classname> on error. | |
| </listitem> | |
| </varlistentry> | |
| <varlistentry> | |
| <term><code>void* operator new[](std::size_t, std::nothrow_t) noexcept;</code></term> | |
| <listitem> | |
| Array <quote>nothrow</quote> <function>new</function>. | |
| Calls <code>operator new[](std::size_t)</code> but if that throws, | |
| returns a null pointer instead. | |
| </listitem> | |
| </varlistentry> | |
| <varlistentry> | |
| <term><code>void* operator new(std::size_t, void*) noexcept;</code></term> | |
| <listitem> | |
| Non-allocating, <quote>placement</quote> single-object <function>new</function>, | |
| which does nothing except return its argument. | |
| This function cannot be replaced. | |
| </listitem> | |
| </varlistentry> | |
| <varlistentry> | |
| <term><code>void* operator new[](std::size_t, void*) noexcept;</code></term> | |
| <listitem> | |
| Non-allocating, <quote>placement</quote> array <function>new</function>, | |
| which also does nothing except return its argument. | |
| This function cannot be replaced. | |
| </listitem> | |
| </varlistentry> | |
| </variablelist> | |
| <para> | |
| They are distinguished by the arguments that you pass to them, like | |
| any other overloaded function. The six flavors of | |
| <function>operator delete</function> | |
| are distinguished the same way, but none of them are allowed to throw | |
| an exception under any circumstances anyhow. (The overloads match up | |
| with the ones above, for completeness' sake.) | |
| </para> | |
| <para> | |
| The C++ 2014 revision of the standard added two additional overloads of | |
| <function>operator delete</function> for <quote>sized deallocation</quote>, | |
| allowing the compiler to provide the size of the storage being freed. | |
| </para> | |
| <para> | |
| The C++ 2017 standard added even more overloads of both | |
| <function>operator new</function> and <function>operator delete</function> | |
| for allocating and deallocating storage for overaligned types. | |
| These overloads correspond to each of the allocating forms of | |
| <function>operator new</function> and <function>operator delete</function> | |
| but with an additional parameter of type <type>std::align_val_t</type>. | |
| These new overloads are not interchangeable with the versions without | |
| an aligment parameter, so if memory was allocated by an overload of | |
| <function>operator new</function> taking an alignment parameter, | |
| then it must be decallocated by the corresponding overload of | |
| <function>operator delete</function> that takes an alignment parameter. | |
| </para> | |
| <para> | |
| Apart from the non-allocating forms, the default versions of the array | |
| and nothrow <function>operator new</function> functions will all result | |
| in a call to either <function>operator new(std::size_t)</function> or | |
| <function>operator new(std::size_t, std::align_val_t)</function>, | |
| and similarly the default versions of the array and nothrow | |
| <function>operator delete</function> functions will result in a call to | |
| either <function>operator delete(void*)</function> or | |
| <function>operator delete(void*, std::align_val_t)</function> | |
| (or the sized versions of those). | |
| </para> | |
| <para> | |
| Apart from the non-allocating forms, any of these functions can be | |
| replaced by defining a function with the same signature in your program. | |
| Replacement versions must preserve certain guarantees, such as memory | |
| obtained from a nothrow <function>operator new</function> being free-able | |
| by the normal (non-nothrow) <function>operator delete</function>, | |
| and the sized and unsized forms of <function>operator delete</function> | |
| being interchangeable (because it's unspecified whether | |
| the compiler calls the sized delete instead of the normal one). | |
| The simplest way to meet the guarantees is to only replace the ordinary | |
| <function>operator new(size_t)</function> and | |
| <function>operator delete(void*)</function> and | |
| <function>operator delete(void*, std::size_t)</function> | |
| functions, and the replaced versions will be used by all of | |
| <function>operator new(size_t, nothrow_t)</function>, | |
| <function>operator new[](size_t)</function> and | |
| <function>operator new[](size_t, nothrow_t)</function> | |
| and the corresponding <function>operator delete</function> functions. | |
| To support types with extended alignment you may also need to replace | |
| <function>operator new(size_t, align_val_t)</function> and | |
| <function>operator delete(void*, align_val_t)</function> | |
| <function>operator delete(void*, size_t, align_val_t)</function> | |
| (which will then be used by the nothrow and array forms for | |
| extended alignments). | |
| If you do need to replace other forms (e.g. to define the nothrow | |
| <function>operator new</function> to allocate memory directly, so it | |
| works with exceptions disabled) then make sure the memory it allocates | |
| can still be freed by the non-nothrow forms of | |
| <function>operator delete</function>. | |
| </para> | |
| <para> | |
| If the default versions of <function>operator new(std::size_t)</function> | |
| and <function>operator new(size_t, std::align_val_t)</function> | |
| can't allocate the memory requested, they usually throw an exception | |
| object of type <classname>std::bad_alloc</classname> (or some class | |
| derived from that). However, the program can influence that behavior | |
| by registering a <quote>new-handler</quote>, because what | |
| <function>operator new</function> actually does is something like: | |
| </para> | |
| <programlisting> | |
| while (true) | |
| { | |
| if (void* p = /* try to allocate memory */) | |
| return p; | |
| else if (std::new_handler h = std::get_new_handler ()) | |
| h (); | |
| else | |
| throw bad_alloc{}; | |
| } | |
| </programlisting> | |
| <para> | |
| This means you can influence what happens on allocation failure by | |
| writing your own new-handler and then registering it with | |
| <function>std::set_new_handler</function>: | |
| </para> | |
| <programlisting> | |
| typedef void (*PFV)(); | |
| static char* safety; | |
| static PFV old_handler; | |
| void my_new_handler () | |
| { | |
| delete[] safety; | |
| safety = nullptr; | |
| popup_window ("Dude, you are running low on heap memory. You" | |
| " should, like, close some windows, or something." | |
| " The next time you run out, we're gonna burn!"); | |
| set_new_handler (old_handler); | |
| return; | |
| } | |
| int main () | |
| { | |
| safety = new char[500000]; | |
| old_handler = set_new_handler (&my_new_handler); | |
| ... | |
| } | |
| </programlisting> | |
| <section xml:id="std.support.memory.notes" xreflabel="Dynamic Memory Notes"><info><title>Additional Notes</title></info> | |
| <para> | |
| Remember that it is perfectly okay to <function>delete</function> a | |
| null pointer! Nothing happens, by definition. That is not the | |
| same thing as deleting a pointer twice. | |
| </para> | |
| <para> | |
| <classname>std::bad_alloc</classname> is derived from the base | |
| <classname>std::exception</classname> class, | |
| see <xref linkend="std.diagnostics.exceptions"/>. | |
| </para> | |
| </section> | |
| </section> | |
| <section xml:id="std.support.termination" xreflabel="Termination"><info><title>Termination</title></info> | |
| <?dbhtml filename="termination.html"?> | |
| <section xml:id="support.termination.handlers" xreflabel="Termination Handlers"><info><title>Termination Handlers</title></info> | |
| <para> | |
| Not many changes here to | |
| <filename class="headerfile"><cstdlib></filename>. | |
| You should note that the | |
| <function>abort()</function> function does not call the | |
| destructors of automatic nor static objects, so if you're | |
| depending on those to do cleanup, it isn't going to happen. | |
| (The functions registered with <function>atexit()</function> | |
| don't get called either, so you can forget about that | |
| possibility, too.) | |
| </para> | |
| <para> | |
| The good old <function>exit()</function> function can be a bit | |
| funky, too, until you look closer. Basically, three points to | |
| remember are: | |
| </para> | |
| <orderedlist inheritnum="ignore" continuation="restarts"> | |
| <listitem> | |
| <para> | |
| Static objects are destroyed in reverse order of their creation. | |
| </para> | |
| </listitem> | |
| <listitem> | |
| <para> | |
| Functions registered with <function>atexit()</function> are called in | |
| reverse order of registration, once per registration call. | |
| (This isn't actually new.) | |
| </para> | |
| </listitem> | |
| <listitem> | |
| <para> | |
| The previous two actions are <quote>interleaved,</quote> that is, | |
| given this pseudocode: | |
| </para> | |
| <programlisting> | |
| extern "C or C++" void f1 (); | |
| extern "C or C++" void f2 (); | |
| static Thing obj1; | |
| atexit(f1); | |
| static Thing obj2; | |
| atexit(f2); | |
| </programlisting> | |
| <para> | |
| then at a call of <function>exit()</function>, | |
| <varname>f2</varname> will be called, then | |
| <varname>obj2</varname> will be destroyed, then | |
| <varname>f1</varname> will be called, and finally | |
| <varname>obj1</varname> will be destroyed. If | |
| <varname>f1</varname> or <varname>f2</varname> allow an | |
| exception to propagate out of them, Bad Things happen. | |
| </para> | |
| </listitem> | |
| </orderedlist> | |
| <para> | |
| Note also that <function>atexit()</function> is only required to store 32 | |
| functions, and the compiler/library might already be using some of | |
| those slots. If you think you may run out, we recommend using | |
| the <function>xatexit</function>/<function>xexit</function> combination | |
| from <literal>libiberty</literal>, which has no such limit. | |
| </para> | |
| </section> | |
| <section xml:id="support.termination.verbose" xreflabel="Verbose Terminate Handler"><info><title>Verbose Terminate Handler</title></info> | |
| <?dbhtml filename="verbose_termination.html"?> | |
| <para> | |
| If you are having difficulty with uncaught exceptions and want a | |
| little bit of help debugging the causes of the core dumps, you can | |
| make use of a GNU extension, the verbose terminate handler. | |
| </para> | |
| <para> | |
| The verbose terminate handler is only available for hosted environments | |
| (see <xref linkend="manual.intro.setup.configure"/>) and will be used | |
| by default unless the library is built with | |
| <option>--disable-libstdcxx-verbose</option> | |
| or with exceptions disabled. | |
| If you need to enable it explicitly you can do so by calling the | |
| <function>std::set_terminate</function> function. | |
| </para> | |
| <programlisting> | |
| #include <exception> | |
| int main() | |
| { | |
| std::set_terminate(__gnu_cxx::__verbose_terminate_handler); | |
| ... | |
| throw <replaceable>anything</replaceable>; | |
| } | |
| </programlisting> | |
| <para> | |
| The <function>__verbose_terminate_handler</function> function | |
| obtains the name of the current exception, attempts to demangle | |
| it, and prints it to <literal>stderr</literal>. | |
| If the exception is derived from | |
| <classname>std::exception</classname> then the output from | |
| <function>what()</function> will be included. | |
| </para> | |
| <para> | |
| Any replacement termination function is required to kill the | |
| program without returning; this one calls <function>std::abort</function>. | |
| </para> | |
| <para> | |
| For example: | |
| </para> | |
| <programlisting> | |
| #include <exception> | |
| #include <stdexcept> | |
| struct argument_error : public std::runtime_error | |
| { | |
| argument_error(const std::string& s): std::runtime_error(s) { } | |
| }; | |
| int main(int argc) | |
| { | |
| std::set_terminate(__gnu_cxx::__verbose_terminate_handler); | |
| if (argc > 5) | |
| throw argument_error("argc is greater than 5!"); | |
| else | |
| throw argc; | |
| } | |
| </programlisting> | |
| <para> | |
| With the verbose terminate handler active, this gives: | |
| </para> | |
| <screen> | |
| <computeroutput> | |
| % ./a.out | |
| terminate called after throwing a `int' | |
| Aborted | |
| % ./a.out f f f f f f f f f f f | |
| terminate called after throwing an instance of `argument_error' | |
| what(): argc is greater than 5! | |
| Aborted | |
| </computeroutput> | |
| </screen> | |
| <para> | |
| The 'Aborted' line is printed by the shell after the process exits | |
| by calling <function>abort()</function>. | |
| </para> | |
| <para> | |
| As this is the default termination handler, nothing need be done to | |
| use it. To go back to the previous <quote>silent death</quote> | |
| method, simply include | |
| <filename class="headerfile"><exception></filename> and | |
| <filename class="headerfile"><cstdlib></filename>, and call | |
| </para> | |
| <programlisting> | |
| std::set_terminate(std::abort); | |
| </programlisting> | |
| <para> | |
| After this, all calls to <function>terminate</function> will use | |
| <function>abort</function> as the terminate handler. | |
| </para> | |
| <para> | |
| Note: the verbose terminate handler will attempt to write to | |
| <literal>stderr</literal>. If your application closes | |
| <literal>stderr</literal> or redirects it to an inappropriate location, | |
| <function>__verbose_terminate_handler</function> will behave in | |
| an unspecified manner. | |
| </para> | |
| </section> | |
| </section> | |
| </chapter> |