Pointer Array try catch
-
Ich verstehe die erste Frage nicht. Oder gibt es nur die eine? Was ich allerdings sehe, ist undefiniertes Verhalten, erzeugt durch Zeile 3.
Gibt es für new auch exceptions wenn nicht genügend Speicher reserviert werden konnte?
Ja. Du erhälst dann eine Exception vom Typ
bad_alloc.
-
Danke für die Antworten, habs jetzt mal so hingeschrieben... wenigstens etwas:
... try { xyz = new float[n]; } catch( std::bad_alloc& excp ) { // nicht genug speicher } catch( ... ) { // etwas anderes }
-
[Rewind] schrieb:
Was ich allerdings sehe, ist undefiniertes Verhalten, erzeugt durch Zeile 3.
Nanu? Ich sehe bloß eine Bedingung, die niemals wahr werden kann.
@Threadersteller: new gibt überhaupt gar keine 0 zurück, sondern schmeißt nur eine Exception im Fehlerfall (außer man nutzt den zurecht selten benutzten nothrow-specifier). Mach es einfach so wie DocShoe zeigt, mit vector wirst du glücklich.asdsaddsaas schrieb:
Danke für die Antworten, habs jetzt mal so hingeschrieben... wenigstens etwas:
... try { xyz = new float[n]; } catch( std::bad_alloc& excp ) { // nicht genug speicher } catch( ... ) { // etwas anderes }Da du nach C++-Stil fragst: Nein, das ist ganz und gar nicht C++-Stil. Das ist Java-Stil. Meines Wissens nach nicht einmal guter Java-Stil.
-
IMO sollte man bad_alloc nicht catchen.
Die Frage ist, wenn du die Exception fängst: Wie willst du darauf reagieren?
Und hier ist die Antwort: Du bist auf das Array angewiesen, also kannst du nur terminieren (oder wie willst du das zurechtbiegen?).
-
Sone schrieb:
IMO sollte man bad_alloc nicht catchen.
Die Frage ist, wenn du die Exception fängst: Wie willst du darauf reagieren?
Und hier ist die Antwort: Du bist auf das Array angewiesen, also kannst du nur terminieren (oder wie willst du das zurechtbiegen?).
Edit: Btw, zu diesem try-catch Block gibt es in einem anderen Thread gerade eine Diskussion, vielleicht kann die jemand verlinken.
Ich könnte dem User sagen dass die Aktion fehlgeschlagen ist und ihn trotzdem weiterarbeiten lassen ... oder ihm zumindestens die Möglichkeit geben, seine Arbeit zu sichern. Nur so ein paar Ideen.
-
Ethon schrieb:
Sone schrieb:
IMO sollte man bad_alloc nicht catchen.
Die Frage ist, wenn du die Exception fängst: Wie willst du darauf reagieren?
Und hier ist die Antwort: Du bist auf das Array angewiesen, also kannst du nur terminieren (oder wie willst du das zurechtbiegen?).
Edit: Btw, zu diesem try-catch Block gibt es in einem anderen Thread gerade eine Diskussion, vielleicht kann die jemand verlinken.
Ich könnte dem User sagen dass die Aktion fehlgeschlagen ist und ihn trotzdem weiterarbeiten lassen ... oder ihm zumindestens die Möglichkeit geben, seine Arbeit zu sichern. Nur so ein paar Ideen.
Klar, dann macht es Sinn.
Eigentlich meine ich auch so Fälle wo wenig Speicher allokiert wird.
Oder setzt du jedes push_back in einen try-catch Block?
Und wo setzt du da die Grenze, ab wie viel Byte würdest du fangen und wo ignorierst du das?Ob der TE jetzt 100 MB oder nur ein 100 000 großes float Array, wissen wir ja nicht
und letztere Größenordnung ist schon wahrscheinlicher.@TE: Es gibt noch
set_new_handler().
-
Für das fehlgeschlagene Verhalten muss eine Statusvariable
statusdefiniert werden.void blub( ... , float *xyz , int &n, int &status )Sie wird auf einen Fehlerwert gesetzt, sobald die Funktion blub nicht glücklich geworden ist.
An
vector<float>habe ich auch schon gedacht. Ich bin mir aber nicht sicher ob die aufrufende Funktion mein&xyz[0]nicht irgendwie in der Größe verändert oder anderweitig gebraucht, so dass meinvectorkorrumpiert wird.
-
Sone schrieb:
Eigentlich meine ich auch so Fälle wo wenig Speicher allokiert wird.
Oder setzt du jedes push_back in einen try-catch Block?
Und wo setzt du da die Grenze, ab wie viel Byte würdest du fangen und wo ignorierst du das?Man fängt und behandelt Fehler dort wo man sie sinnvoll behandeln kann.
Irgendwie logisch, oder?
-
hustbaer: Ja, du hast Recht.
asdasdasdasd schrieb:
Für das fehlgeschlagene Verhalten muss eine Statusvariable
statusdefiniert werden.void blub( ... , float *xyz , int &n, int &status )Sie wird auf einen Fehlerwert gesetzt, sobald die Funktion blub nicht glücklich geworden ist.
Man könnte auch den Status zurückgeben.
-
asdasdasdasd schrieb:
An
vector<float>habe ich auch schon gedacht. Ich bin mir aber nicht sicher ob die aufrufende Funktion mein&xyz[0]nicht irgendwie in der Größe verändert oder anderweitig gebraucht, so dass meinvectorkorrumpiert wird.Und wie würde das bei einem mit new erzeugten Array sein? Es gibt kein renew in C++.
-
Sone schrieb:
hustbaer: Ja, du hast Recht.
asdasdasdasd schrieb:
Für das fehlgeschlagene Verhalten muss eine Statusvariable
statusdefiniert werden.void blub( ... , float *xyz , int &n, int &status )Sie wird auf einen Fehlerwert gesetzt, sobald die Funktion blub nicht glücklich geworden ist.
Man könnte auch den Status zurückgeben.
Auf die Signatur der Funktion habe ich leider keinen Einfluss.
SeppJ schrieb:
asdasdasdasd schrieb:
An
vector<float>habe ich auch schon gedacht. Ich bin mir aber nicht sicher ob die aufrufende Funktion mein&xyz[0]nicht irgendwie in der Größe verändert oder anderweitig gebraucht, so dass meinvectorkorrumpiert wird.Und wie würde das bei einem mit new erzeugten Array sein? Es gibt kein renew in C++.
Mein Wirkungsbereich ist leider nur innerhalb dieser Funktion, wahrscheinlich wird dann
reallocoder Ähnliches verwendet.
-
realloc funktioniert bei new[] auch nicht.
new[] bietet dir praktisch keinen Vorteil gegenüber std::vector, wohl aber Nachteile.
-
asdasdasdasd schrieb:
Mein Wirkungsbereich ist leider nur innerhalb dieser Funktion, wahrscheinlich wird dann
reallocoder Ähnliches verwendet.Auch dies ist unmöglich (selbst wenn man das undefinierte Verhalten ignoriert), da die Funktion den neuen Wert des Pointers nicht nach außen geben kann, bei dieser Signatur.
void funktioniert_nicht(int *foo) { foo = (int*) realloc(foo, 24); // Ziemlich böse Idee, aber wir machen das mal einfach } int main() { // Welche Szenarien sind nun denkbar, in denen die Funktion "funktioniert_nicht" // wie angedacht funktioniert? Folgende Aufrufe sind alle syntaktisch korrekt, aber etwas schlimmes // passiert. Das liegt nicht an den Aufrufen, sondern weil "funktioniert_nicht" falsch ist. std::vector<int> a; funktioniert_nicht(&a[0]); // Bumm! Klar warum. int *b = new int[2]; funktioniert_nicht(b); // Bumm! realloc und new sind nicht kompatibel. // Doppelbumm! Unser b hat sich nicht verändert, aber der Speicher ist futsch. int c[4]; funktioniert_nicht(c); // Bumm! Statisches Array reallokiert int* d = (int*) malloc(4); funktioniert_nicht(d); // Bumm! Unser d hat sich nicht verändert, aber der Speicher ist futsch }Du machst dir völlig umsonst Panik.
-
Zunächst einmal denke ich wäre es am besten ein set_new_handler() zu benutzen um speicherfehler auszuschließen -> Micrsoft hat da ne gute hilfe. Wegen der Übergabe (kann leider kein Code gerade Zeigen) hänge gerade im Unterricht.
Objekt normal übergeben "void bla(Operator name)"
dann Inhalt zwischenspeichern und alten speicher freigeben "delete [] name;"
neuen speicher mit new anlegen (bei z.B. char länge auslesen mit
"variable =strlen(name)" und in new name(variable) einsetzen)) dann
z.B. neue Adresse zurückgeben
-
blalala schrieb:
Zunächst einmal denke ich wäre es am besten ein set_new_handler() zu benutzen um speicherfehler auszuschließen
Es gibt da doch kein "Bestes". Je nach dem wo es Sinn macht, behandelt man die Fehler, das hat doch schon hustbaer gesagt.
Btw. habe ich den Link dazu bereits angegeben, falls es der TE ihn jetzt haben will:
Sone schrieb:
@TE: Es gibt noch
set_new_handler().
-
Supi, habe wieder jede Menge gelernt. Danke an alle Beitragenden
