definierten Ausnahmen in <stdexcept>
(z.B. std::logic_error
, std::runtime_error
und ihre Subklassen wie std::system_error
) haben Konstrukteure String Argumente erwarten, z.B .:Wie erstellt man eine <stdexcept> oder <system_error> Ausnahme ohne zu werfen?
domain_error(const string& what_arg);
domain_error(const char* what_arg);
mit Nachbedingungen
strcmp(what(), what_arg.c_str()) == 0
strcmp(what(), what_arg) == 0
sind. Es ist nicht erforderlich, dass diese an die Konstruktoren übergebenen Argumente während der Lebensdauer dieser Ausnahmen gültig bleiben. Daher können Sie nur sicherstellen, dass die Nachbedingungen erfüllt sind, indem Sie doppelt kopieren und diese dynamischen Zeichenfolgen speichern. Dies erfordert Speicher, so nehme ich an, dass ihre Konstruktion selbst std::bad_alloc
oder ähnliches werfen kann, was normalerweise am meisten unerwartet ist. Dies verursacht Probleme, weil jeder Code Beispiel, das ich in den wilden Menschen ermutigt gesehen habe, Code zu schreiben, wie
if (haveError)
throw std::runtime_error("BOO!"); // May throw std::bad_alloc instead?!
während es viel sicherer zu sein scheint die Ausnahme vorher in einem anderen Ort zu konstruieren, zum Beispiel:
Das macht mich sehr vorsichtig von Bibliotheken, die solche Ausnahmen werfen, zB sogar regex_error
von <regex>
in C++ 11 !!!
Warum haben diese Ausnahmen keine no-throw/noexcept-Konstruktoren? Haben die C++ - Kernrichtlinien ein Mitspracherecht?
PS: Persönlich hätte ich what()
eine reine abstrakte Methode an dieser Stelle in der Ausnahme-Stammbaum-Kette verlassen.
EDIT 2017.09.10: Hier ist ein PoC zeigt, dass std::runtime_error
Bau eines std::bad_alloc
stattdessen werfen kann:
#include <cstddef>
#include <cstdlib>
#include <new>
#include <stdexcept>
#include <string>
bool throwOnAllocate = false;
void * operator new(std::size_t size) {
if (!throwOnAllocate)
if (void * const r = std::malloc(size))
return r;
throw std::bad_alloc();
}
void operator delete(void * ptr) { std::free(ptr); }
int main() {
std::string const errorMessage("OH NOEZ! =(");
throwOnAllocate = true;
throw std::runtime_error(errorMessage);
}
Ja, es ist möglich, dass eine Funktion wegen eines Mangels an unbenutztem Heapspeicher in diesem Moment nicht ausgeführt wird, aber die Anzeige des Fehlers 'alert' blockiert das System oder stürzt ab. Zum Glück ist das selten. –
"obwohl es viel sicherer erscheint, die Ausnahme vorher an anderer Stelle zu konstruieren" - verstehe ich nicht. Wenn Ihr 'throw std :: runtime_error (" BOO! ");' Eine andere Ausnahme ausgelöst hätte, weil zu wenig Speicher zur Verfügung steht, würde die Zuweisung des 'std :: runtime_error' zuvor * erfordern, dass dieser Speicher verfügbar ist. Die einzige Änderung, die ich sehe, ist, dass 'bad_alloc' früher geworfen würde. – hvd
@hvd früher in einem besseren oder ** erwarteten Kontext, z. 'neues A()'. Es ist schrecklich, eine Ausnahme zu haben **, die während der ** Fehler/Ausnahmebehandlung (C++ 11 Exception Nesting Contexts included) unerwartet ausgelöst ** wird. – jotik