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