Exceptions in C++ (Exceptions in C++), Lektion, Seite 722507
https://www.purl.org/stefan_ram/pub/exceptions_c++ (Permalink) ist die kanonische URI dieser Seite.
Stefan Ram
C++-Kurs

Exceptions in C++ 

Auftreten von Ausnahmen

main.cpp

#include <string>

int main()
{ ::std::string abc{ "abc" };
abc.at( 8 )= 'x'; }

Bei Zugriffen auf nicht existierende Stellen wirft ».at(…)« eine Ausnahme (exception). Das Programm wird abgebrochen. Der Wurf einer Ausnahme signalisiert meist einen Fehler, der erst während des Programmablaufs bemerkt wird, einen Laufzeitfehler.

Dies ist unter Umständen besser als bei Reihungszugriffen, wo die Verwendung eines unzulässigen Index-Werts unter Umständen unbemerkt bleibt.

Sagt man nur „werfen“ (intransitiv), so meint man damit „eine Ausnahme werfen“. Wir können also sagen, daß »abc.at( 8 )« in dem Programm wirft.

n3797, 21.4.5 (umformatiert und gekürzt)
reference at( size_type pos );
Throws: out_of_range if pos >= size().
n3797, 19.2, 19.2.5 (umformatiert und gekürzt)
<stdexcept>
namespace std { class out_of_range … }
main.cpp

#include <iostream>
#include <ostream>
#include <string>

using namespace ::std::literals;

void function()
{ ::std::cout << "Öffnen der Datei"s << '\n';
"abc"s.at( 5 );
::std::cout << "Schließen der Datei"s << '\n'; }

int main()
{ ::std::cout << "Öffnen der Datei"s << '\n';
"abc"s.at( 5 );
::std::cout << "Schließen der Datei"s << '\n'; }

::std::cout
3

Hinweis für den Dozenten  ► Strukturierte Programmierung:

{ öffne Datei

schreibe in Datei ------- Ausnahme ---------.

schließe Datei v

Fangen spezieller Ausnahmen

main.cpp

#include <iostream>
#include <ostream>
#include <string>
#include <stdexcept>

int main()
::std::string abc{ "abc" };

try
  { 
abc.at( 2 )= 'x'; 
    ::std::
cout << "Index innerhalb  des zulaessigen Bereichs.\n"; }
catch( ::std::out_of_range exception )
  { ::std::
cout << "Index ausserhalb des zulaessigen Bereichs.\n"; }

try
  { 
abc.at( 8 )= 'x'; 
    ::std::
cout << "Index innerhalb  des zulaessigen Bereichs.\n"; }
catch( ::std::out_of_range exception )
  { ::std::
cout << "Index ausserhalb des zulaessigen Bereichs.\n"; }}

::std::cout
Index innerhalb  des zulaessigen Bereichs.
Index ausserhalb des zulaessigen Bereichs.

Bei vorhersehbaren Fehlern durch die Programmierung ist es aber besser, den Fehler nicht durch ein nachträgliches Fangen zu behandeln, sondern durch eine vorherige Prüfung zu vermeiden. Ausnahmen sollten eher dazu verwendet werden, um nicht vorhersehbare Fehler zu erkennen, wie etwa den Ausfall eines Datenträgers. Da solche Fehler aber in Programmbeispielen nicht so einfach gezeigt werden können, wurde hier das obige Beispiel gezeigt. Das folgende Programm zeigt, wie der Fehler besser vermieden werden sollte.

main.cpp

#include <iostream>
#include <ostream>
#include <string>
#include <stdexcept>

int main()
::std::string abc{ "abc" };

  if( 2 < abc.size() )abc.at( 2 )= 'x';
  else ::std::cerr << "Index ausserhalb des zulaessigen Bereichs.\n";


  if( 8 < abc.size() )abc.at( 8 )= 'x';
  else ::std::cerr << "Index ausserhalb des zulaessigen Bereichs.\n"; }

::std::cout

Index innerhalb  des zulaessigen Bereichs.
Index ausserhalb des zulaessigen Bereichs.

Fangen beliebiger Ausnahmen

main.cpp
#include <iostream>
#include <ostream>
#include <string>
#include <stdexcept>
int main()
{ ::std::string abc{ "abc" };
  try
  { abc.at( 8 )= 'x'; }
  catch( 
... )
  { ::std::cout << "Irgendeine Ausnahme ist aufgetreten.\n"; }}
::std::cout
Irgendeine Ausnahme ist aufgetreten.

Fangen und Weiterwerfen einer Ausnahme

#include <iostream>
#include <ostream>
#include <string>
#include <stdexcept>

int main()
{ ::std::string abc{ "abc" };
try
{ abc.at( 8 )= 'x'; }
catch( ... )
{ ::std::cout << "Irgendeine Ausnahme ist aufgetreten.\n"; throw; }}

::std::cout
Irgendeine Ausnahme ist aufgetreten.
(Programmabbruch)

Exemplarfreigaben

Beim Verlassen eines Blocks durch das Werfen einer Ausnahme werden die im Block angeforderten Exemplare wieder so automatisch aufgelöst, wie dies auch beim normalen Verlassen des Blocks geschehen wäre. Andere Aufräumarbeiten, die am Ende eines Blocks programmiert wurden, werden aber durch die Ausnahme eventuell übersprungen. Wenn es sichergestellt werden soll, daß diese auf jeden Fall ausgeführt werden, so müssen sie in einem catch-Block wiederholt werden. Es gibt allerdings noch eine elegantere Lösung (exception-safety, RAII) dieses Problems, die später behandelt werden soll.

Wenn der Compiler weiß, daß eine Ausnahme nicht abgefangen wird, kann er sofort »::std::terminate« aufrufen (und alle Bereinigungsaktionen überspringen).

Cast mit Wertprüfung

narrow_cast.txt
template< class Target, class Source > 
Target narrow_cast( Source v )
{ auto r = static_cast< Target >(v);
if( static_cast< Source >( r )!= v )
throw runtime_error( "narrow_cast<>() failed" );
return r; }

Scheitern von Speicheranforderungen

Wenn ein Programm immer wieder Objekte an einen Vektor anfügt, kann es irgendwann einmal zu einer Situation kommen, in der keine Speicherplatz mehr verfügbar ist. Dann können die von Behältern der Standardbibliothek verwendeten Allokatoren entsprechende Ausnahmen vom Typ »bad_alloc« werfen.

In der Praxis beobachtet man jedoch manchmal, daß Geräte in solch einer Situation versuchen, den verfügbaren Hauptspeicher durch Verwendung von Festplattenspeicher zu erweitern, wodurch bei extremen Speicheranforderungen das gesamte Gerät so verlangsamt wird, daß es nicht mehr bedienbar ist. Das Gerät friert dann praktisch ein oder wird vom Bediener neu gestartet, bevor eine Ausnahmesituation »bad_alloc« beobachtet werden kann.

Hinzu kommt noch, daß es nicht ganz einfach ist, mit einer solche Ausnahme umzugehen, da es sein könnte, daß beim Fehlen von Speicherplatz auch der Programmteil zur Behandlung der Fehlersituation nicht mehr richtig ausgeführt werden kann.

C++ 2016-11
17.5.5.12p4 (was: 17.6.5.12p4):
Any other functions defined in the C++ standard library that do not have an exception-specification may throw implementation-defined exceptions unless otherwise specified.
C++ 2016-11
20.10.9 The default allocator [default.allocator]
...
20.10.9.1 allocator members [allocator.members]
...
T* allocate(size_t n);
4 Throws: bad_alloc if the storage cannot be obtained.

Seiteninformationen und Impressum   |   Mitteilungsformular  |   "ram@zedat.fu-berlin.de" (ohne die Anführungszeichen) ist die Netzpostadresse von Stefan Ram.   |   Eine Verbindung zur Stefan-Ram-Startseite befindet sich oben auf dieser Seite hinter dem Text "Stefan Ram".)  |   Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram. Schlüsselwörter zu dieser Seite/relevant keywords describing this page: Stefan Ram Berlin slrprd slrprd stefanramberlin spellched stefanram722507 stefan_ram:722507 Exceptions in C++ Stefan Ram, Berlin, and, or, near, uni, online, slrprd, slrprdqxx, slrprddoc, slrprd722507, slrprddef722507, PbclevtugFgrsnaEnz Erklärung, Beschreibung, Info, Information, Hinweis,

Der Urheber dieses Textes ist Stefan Ram. Alle Rechte sind vorbehalten. Diese Seite ist eine Veröffentlichung von Stefan Ram.
https://www.purl.org/stefan_ram/pub/exceptions_c++