Excptions, static/dynamic?
-
Ein (C-) Array wird als Zeiger behandelt.
int* Fn() { int array[20]; return array; // == return &array[0] => pointer (s. auch Funktionsdeklaration) }Es findet also kein Kopiervorgang statt. Der Zeiger zeigt auf das lokal existierende Feld und nach dem Funktionsaufruf existiert dieses nicht mehr.
Das Problem tritt im ueberigen bei Exceptions in dem Zusammenhang auch auf.
Sprichvoid Fn1() { char message[] = "catch me if you can"; throw message; }kopiert den Zeiger auf das Array und wirft diesen. Es gibt genauso Probleme. Deshalb sollte man nur Sachen werfen, die "ordentlich" kopiert werden koennen.
Also Exceptionklasse schreiben mit Copyconstructor.
Und grundsaetzlich eher std::string und std::vector nutzen, die haben schon einen funktionierenden Copy-Ctor.Gruss,
DeSoVoDaMu
-
Wie löst man denn das problem mit arrays ohne der Methode eine Referenz eines Arrays zu geben? Garnicht?
Und was ich mich in dem Fall noch frage ist, wenn ich ein throw new Exception(); habe, und die Exception als Referenz fange, kopiert mir der Compiler die Exception auch? Weil dann hätte ich ja mit new Speicher reerviert und hätte mit dem throw keinen Verweis mehr auf diese Adresse (also wenn er kopiert) Oder kopiert er bei new nicht?
-
Es ist halt besser, keine Arrays zu throwen - wozu auch? Zur not verpackst du die halt schön in eine Klasse, die einen eigenen Copy-Konstruktor, etc hat.
Zu dem new-Problem: Wenn du mit throw new myType; ein Objekt wirfst, ist der Typ des von new zurückgegeben Werts Zeiger auf myType, d.h. der Zeiger wird kopiert. Das bedeutet zwei Sachen
-
Du musst mit catch(myType *exception) fangen, bzw. übertriebenermaßen wenn man immer Referenzen catchen will: catch(myType *&exception)
-
Um ein Memory-Leak zu verhindern, musst du im catch-Handler delete auf den Zeiger aufrufen.
Felix
-
-
So würdest Du einen Zeiger auf ein Exception-Objekt werfen, also ein Exception*. Der catch-Handler für die Referenz würde garnicht erst angesprungen, weil er einen ganz anderen Typ erwartet. Zeiger-auf-T und T (bzw. T&) sind genauso unterschiedliche Typen wie double und string

Das Problem mit den Arrays (und auch jeder anderen Art von rohen Zeigern) löst man in C++ üblicherweise mit Kapseln wie z.B. vector, string oder den Anforderungen entsprechenden Smartpointern.
-
DeSoVoDaMu schrieb:
Und grundsaetzlich eher std::string und std::vector nutzen, die haben schon einen funktionierenden Copy-Ctor.
Das sollte man sich an dieser Stelle allerdings genau überlegen: die Konstruktion eines Exceptionobjekts sollte nicht fehlschlagen können (und das kann bei std::string oder std::vector ohne weiteres schiefgehen), andernfalls kommen wir sehr schnell bei terminate() an.
-
DeSoVoDaMu schrieb:
Das Problem tritt im ueberigen bei Exceptions in dem Zusammenhang auch auf.
Sprichvoid Fn1() { char message[] = "catch me if you can"; throw message; }kopiert den Zeiger auf das Array und wirft diesen. Es gibt genauso Probleme. Deshalb sollte man nur Sachen werfen, die "ordentlich" kopiert werden koennen.
versuch mal so ähnlich:
(ich weiss aber nicht ob sowas in C++ compiliert)void Fn1() { throw "catch me if you can"; }dabei dürfte nur ein pointer herumgereicht werden. der text ist 'fix' und bleibt erhalten.

-
Das geht, das weiß ich
Aber wer wirft schon ein char Array...
-
Seikilos schrieb:
Das geht, das weiß ich
Aber wer wirft schon ein char Array...der DeSoVoDaMu z.b. macht das.

...oder man 'throwed' einen pointer auf irgendwas statisches (eine feste struct oder so), um die möglichkeit auszuschliessen, dass beim kopieren was schief geht (wie camper schon angedeutet hat).

-
Apeman schrieb:
...oder man 'throwed' einen pointer auf irgendwas statisches (eine feste struct oder so), um die möglichkeit auszuschliessen, dass beim kopieren was schief geht (wie camper schon angedeutet hat).

Aber dabei bitte keine Kopierphobie entwickeln, statics haben auch genug potentielle Nachteile

-
Apeman schrieb:
Seikilos schrieb:
Das geht, das weiß ich
Aber wer wirft schon ein char Array...der DeSoVoDaMu z.b. macht das.

Ich zeige vielleicht wie es geht, aber machen tu ich das nicht

-
(Ich machs auch nicht aber...) müsste das mit dem String werfen nicht gehen? Rohe Strings werden doch in der Data-Section des Programms gespeichert, der Zeiger müsste doch seinen Lebtag gültig sein..?
-
camper schrieb:
DeSoVoDaMu schrieb:
Und grundsaetzlich eher std::string und std::vector nutzen, die haben schon einen funktionierenden Copy-Ctor.
Das sollte man sich an dieser Stelle allerdings genau überlegen: die Konstruktion eines Exceptionobjekts sollte nicht fehlschlagen können (und das kann bei std::string oder std::vector ohne weiteres schiefgehen), andernfalls kommen wir sehr schnell bei terminate() an.
Jupp.
Bei Exceptions ist entweder viel Handarbeit angesagt, oder man verwendet z.B. boost::shared_ptrstd::string o.ä.
Ein boost::shared_ptr kann schliesslich no-throw kopiert werden...
-
Badestrand schrieb:
(Ich machs auch nicht aber...) müsste das mit dem String werfen nicht gehen? Rohe Strings werden doch in der Data-Section des Programms gespeichert, der Zeiger müsste doch seinen Lebtag gültig sein..?
das denke ich auch. ich kann zwar nur C, aber ich nehme an, dass in C++ stringkonstanten ebenfalls über die gesamte programmlaufzeit ihre gültigkeit behalten. was soll schlecht sein am 'throwen' eines rohen C-strings? (ausser dass es der denkweise von C++ fans zuwider ist, nach der ja alles unnötig verkompliziert werden muss).

-
Apeman schrieb:
ich kann zwar nur C, aber ich nehme an, dass in C++ stringkonstanten ebenfalls über die gesamte programmlaufzeit ihre gültigkeit behalten. was soll schlecht sein am 'throwen' eines rohen C-strings?
Hat sich denn jemand dagegen ausgesprochen?
(ausser dass es der denkweise von C++ fans zuwider ist, nach der ja alles unnötig verkompliziert werden muss).
Dafür haben die C-Fans nach der dritten Parameterübergabe vergessen, ob der rohe C-String jetzt auf dem Heap, Stack, Datenbereich oder sonstwo lag
:p
-
Ihr reisst meinen Text alle aus dem Zusammenhang

Ich habe mich fuer eine Exceptionklasse ausgesprochen.
Der Part zu std::string und std::vector war allgemein, weil der OP ein C-Array aus einer Funktion zurueckgeben wollte. Aber: ja, ihr habt recht!
-
Apeman schrieb:
...ausser dass es der denkweise von C++ fans zuwider ist, nach der ja alles unnötig verkompliziert werden muss...
Seltsamerweise kommen 80% der Anfragen/Probleme mit "Zeichenketten" hier im Zusammenhang mit NTBS und werden zu 90% durch den Einsatz von std::string gelöst.
Außerdem wird jedesmal der Code um 70% kürzer...
Jaja, wir C++er müssen immer alles komplizierter machen ...

Gruß,
Simon2.