C++ Biblithek in C Programm: keine Exceptions ?

Ich habe eine (dynamisch gelinkte) Bibliothek in C++ geschrieben (Linux), die ich nun als Modul in den Apache-Server (C-Code) (logischerweise auch Linux) einbinden möchte. Das ganze klappt auch soweit ganz gut.

Mein Problem ist allerdings, dass die Bibliothek Exceptions verwendet, um Fehler zu melden. Jedes Mal, wenn jedoch eine Exception geworfen wird, stirbt der entsprechende Server-Prozess mit einem SIG_ABORT (sollte eigentlich einen core-dump liefern, was es allerdings nicht tut) und ohne weitere Angabe von Gründen: kein Error-Log, keine Fehlermeldung, nix.

Ich denke nicht, dass das Problem mit dem Apache zusammenhängt, sondern ein allgemeines Problem ist, wenn man versucht C und C++ zu mixen.

Meine Vermutung: der Startup-Code der Bibliothek wird von C nicht korrekt aufgerufen und das Exception-Handling daher nicht initialisiert.

Hat jemand eine Idee, was man dagegen tun kann?

Ok, man könnte natürlich den Apache mit nem C++ Compiler neu bauen, aber das will man nicht wirklich… :wink:

Thanx im voraus!

Marc

Moin,

Mein Problem ist allerdings, dass die Bibliothek Exceptions
verwendet, um Fehler zu melden. Jedes Mal, wenn jedoch eine
Exception geworfen wird, stirbt der entsprechende
Server-Prozess mit einem SIG_ABORT (sollte eigentlich einen
core-dump liefern, was es allerdings nicht tut) und ohne
weitere Angabe von Gründen: kein Error-Log, keine
Fehlermeldung, nix.

  1. Fängst Du den SIGABRT?
  2. Bei SuSE sind cores in der /etc/profile abgestellt.

Thorsten

Hi,

wenn eine Exception nicht abgefangen wird, ist ABRT schon das richtige Verhalten. Vielleicht handelt es sich um ein Problem, das nicht von der Lib selbst behandelt werden kann. Fang doch die Exceptions einfach selbst - das ist eleganter, als das SIGABRT zu fangen, ausserdem kriegst Du da noch Infos in der Exception.

Gruss

Thorsten

Hallo!

Erstmal danke für eure Posts…

Ich fürchte nur, ihr habt mich da ein wenig mißverstanden (Vielleicht war es auch ein wenig unglücklich formuliert, sorry).

Also: Ich verwende in meiner Bibliothek schon einen try-throw-catch Block (Genauer gesagt besteht meine Test-Bibliothek zur Zeit nur genau aus diesem). Das ganze sieht in etwa wie forlgt aus:

int handler(request_rec *r){
  try{
    cerr

Moin,

Fang doch die Exceptions einfach selbst

Das geht? Hast Du mal ein Stichwort/Manpage?

Thorsten

Hi,

Fang doch die Exceptions einfach selbst

Das geht? Hast Du mal ein Stichwort/Manpage?

Ja, das ist der Sinn von Exceptions, man kann Fehler leicht abfangen, wenn man das aber nicht tut wird das Programm bendet (was ja bei unbehandelten Fehlern durchaus sinnvoll ist).
Eine Exception ist ein Objekt. In der STL (Standard Template Library, die C++ standard Bibliothek) sind alle Exceptions vom Typ exception abgeleitet (vererbt). Ich leite alle meine Exceptions ebenfalls von diesem Typ und ich schaetze jeder vernuenftige Programmierer tut das. Daher solltest Du den Typ auf jeden Fall abfangen. Beispiel:

int main() {
 try {
 f(i);
 } catch(exception e) {
 cout 
try {...} fuehrt Deinen Code aus. Wenn dieser Code eine Exception wirft, wird geschaut, ob der Typ der Exception zu einem der Catch-clauses passt. Wenn die Exception vom Typ exception abgeleitet ist, wird der Code im ersten catch-Scope ausgefuehrt. what() ist eine Methode (member-function) von exception, die const char\* zurueck gibt (also einen C-String, der Informationen ueber den Fehler enthaelt). Wenn Du die tatsaechlichen Typen abfaengst, kannst Du statt eine Ausgabe zu machen den Fehler auch behandeln.
Der zweite Catch-Scope faengt jede beliebige Exception ab (mit ...). Daher kann er aber auch mangels Informationen den Fehler kaum behandeln.
Exceptions koennen ueberall behandelt, nicht nur in der main(). Meiner Ansicht nach sollte allerdings alles in mein in einem try{} stehen, dann hat man schon mal alle exceptions abgefangen und kann eine ordentlich Ausgabe machen bevor man abbricht. Weiter unten im Code koennen dann zusaetzlich spezifischere Fehlerbehandlungen stattfinden, wenn gewuenscht.
Dazu muss die main natuerlich als C++ compiliert werden, das sollte aber kein Problem sein, wenn Du eh schon C/C++ mischst.
So eine einfache Referenz habe ich nicht, Exceptionhandling ist aber z.B. im zweiten Band von "Thinking in C++" von Bruce Eckel sehr gut erklaert. Das Buch kannst Du kostenlos unter http://www.mindview.net/ downloaden.

Gruss

Thorsten
  1. Fängst Du den SIGABRT?

Nein, Ich will ja keine Signalbehandlung via logjump und so machen, sondern „echte“ C++ Exceptions mit try-catch.

  1. Bei SuSE sind cores in der /etc/profile abgestellt.

Danke das ist nen guter Hinweis, vielleicht hilft das was

Marc

Moin,

  1. Fängst Du den SIGABRT?

Nein, Ich will ja keine Signalbehandlung via logjump und so
machen, sondern „echte“ C++ Exceptions mit try-catch.

Ich weiß nicht viel von dieser Problematik, aber ich kenne kein C-Schlüsselwort ‚try‘.
Wenn die Exceptions im C-Teil als SIGABRT gesehen werden, mußt Du den wohl fangen.

Thorsten

Moin,

Ich fürchte nur, ihr habt mich da ein wenig mißverstanden

Stimmt.

Thorsten

kein C-Schlüsselwort ‚try‘.

‚try‘, ‚catch‘ und ‚throw‘ sind auch Spracherweiterungen von C++. ‚try‘ leitet einen Code-Block ein, in dem eine Exception auftreten kann, eine ‚catch‘ Block gibt einen Codeberech an, der ausgeführt werden soll, wenn eine Exception eines bestimmten Typs geworfen wird (mit ‚throw‘, z.B aus einer Funktion innerhalb des ‚try‘ Blocks). Typ kann dabei alles sein: ein int, ein float, ein const char *. Eigentlich eine sehr praktische sache mit der man sich ne menge geschachtelte if-else ersparen kann.

Wenn sie denn mal ordentlich funktionieren würden :wink:

Marc

Hi,

int handler(request_rec *r){
  try{
    cerr

cerr seinerseits eine Exception. Nimm das mal raus, damit
kannst Du diese Moeglichkeit ausschliessen.

Hab ich auch schon probiert, macht aber leider keinen Unterschied

Wenns das nicht ist scheints ein Fehler im Compiler/Linker :sein … neuere Version testen?

Ich fürchte, dass es wohl erstmal darauf hinauslaufen wird. Naja, wir wollten hier eh bei Zeiten mal nen aktuelleres SuSE einspielen.

Aber nicht mehr heute, ich mach getz Feierabend…

Gruss, Marc

Moin,

Das war jetzt ein Mißverständnis: Das Prinzip von try/catch kenne ich, ich wollte wissen, ob man die Exceptions in C fangen kann. Denn so hatte ich die Problembeschreibung verstanden.

Gruss

Thorsten

Nabend!

Ich glaube, wir sind alle ein bisschen daneben heute :wink:

Also try-catch funktioniert in C nicht. Und diese Art von Excpetion kann man meines Wissens nach auch nicht fangen.

Aber das ist auch nicht mein Problem.

Ich habe ein in C geschriebenes Hauptprogramm, das ich nicht geschrieben habe und auch nicht direkt ändern kann. Dieses bietet allerdings die Möglichkeit zur laufzeit Module in Form von dynamisch gelinkten Bibliotheken hinzuzuladen. Diese Bibliothek ist bis auf einige winige feste Schnittstellen-Funktion die als extern „C“ deklariert sind vollständig in C++ geschieben. Diese Bibliothek benutzt C++ Exceptions zur Fehlerbehandlung, d.h. sie wirft zum einen wild mit Exceptions um sich, sie besitzt aber auch gleichzeitig eine übergeordnete Handler-Funktion, welche ALLE evtl. auftretende Exceptions behandeln soll, damit das in C geschriebene Hauptprogramm damit nichts zu tun hat.

Leider funktioniert diese strikte Trennung offenbar nicht richtig, d.h. nicht alle für das Exception-Handling relevanten Teile liegen werden mit in die Bibliothek gepakt bzw. die entsprechden Initialisierungs-Routinen in der Bibliothek werden beim Laden durch das Hauptprogramm nicht korrekt ausgeführt.

Gruss, Marc

Moin,

Das war jetzt ein Mißverständnis: Das Prinzip von try/catch
kenne ich, ich wollte wissen, ob man die Exceptions in
C fangen kann. Denn so hatte ich die
Problembeschreibung verstanden.

Mahlzeit!

Ich habe jetzt herausgefunden, dass es devinitiv nicht am Compiler liegt!

Ich habe gerade nochmal ein kleines C Hauptprogramm geschrieben
dass nichts anderes macht als meine Test-Bibliothek zu laden und
die Funktion mit der Exception aufruft. Das ganze funktioniert dann wunderbar…

Also muss es sich doch um ein apache-spezifisches Problem handeln.

Werde jetzt noch mal die Leute bei www.apache.org löchern…

Trotzdem danke für Eure Mühe!

Gruß, Marc

Hi,

Ich habe jetzt herausgefunden, dass es devinitiv nicht am
Compiler liegt!

Na, dann kanns immer noch am Linker liegen. Ich weiss ja nun nicht, wie g++ (oder was verwendest Du?) exceptions implementiert … vielleicht ueber jumps? Meines Wissens erzeugt das Werfen einer Exception einen ziemlichen Overhead (nicht das schreiben, nur das tatsaechliche werfen) - da muss also irgendwas abgehen. Compilierst Du den gesamten Code selbst, oder nur Dein Stueck? Vielleicht liegts an unterschiedlichen Compiler-Versionen …

Gruss

Thorsten

Hallo

Na, dann kanns immer noch am Linker liegen. Ich weiss ja nun
nicht, wie g++ (oder was verwendest Du?) exceptions
implementiert … vielleicht ueber jumps?

Ja, richtig, ich verwende gcc/g++ (genauer gcc version egcs-2.91.66 19990314/Linux (egcs-1.1.2 release)). Als Linker steckt da der ld hinter, wird aber vom Compiler selbst aufgerufen, d.h. ich linke das nicht selbst von Hand. Habe gelesen, dass das so der richtige Weg ist, weil manche Compiler beim Linker-Aufruf noch eigene Parameter übergeben (Bibliotheken und so)

Ich vermute auch, dass da jumps hinterstecken, aber wie es genau funtioniert, weiss ich auch (noch) nicht. Evtl. werde ich mal bei gcc nachfragen…

Meines Wissens
erzeugt das Werfen einer Exception einen ziemlichen Overhead
(nicht das schreiben, nur das tatsaechliche werfen) - da muss
also irgendwas abgehen.

Ja, stimmt. Wobei das eigentliche Werfen wohl nicht das Problem ist, sondern das Aufräumen des Stacks. Der muss dann ja die ganzen evtl. Angelegten Objekte freigeben und so

Compilierst Du den gesamten Code
selbst, oder nur Dein Stueck? Vielleicht liegts an
unterschiedlichen Compiler-Versionen …

Nee, das Hauptprogramm (der Apache-Webserver) ist nicht von mir, schön wärs :wink:. Der war schon vorkompiliert beim SuSE dabei. Und damit man ihn nicht jedesmal komplett neubauen muss, gibt es halt die Möglichkeit, ihn mit selbstgeschriebenen Bibliotheken zu erweitern. Das sind dann shared libs. Und diese Bibliothek ist komplett von mir.

Das mit den unterschidlichen Compiler-Versionen ist noch ne Möglichkeit, allerdings glaube (hoffe?) ich, dass das nicht der Fall ist, weil es dann wohl keine andere Möglickeit mehr gibt, als den Apache selbst neu zu bauen, was ziemlich aufwändig ist.

Aber ich bin auch bisher immer davon ausgegangen, dass die Softwarepakete einer Distribution auch immer mit dem damit ausgelieferten Compiler gebaut werden, damit es eben keine Linker-Probleme gibt. Aber wer weiss das schon?

Gruss, Marc

Wenn man nur lange genug nachhakt…
…dann bekommt man sogar von den Apache-Leuten eine Antwort. Und das hat mich jetzt NUR 2 Wochen gekostet :frowning:


That doesn’t suprise me. try/catch semanitics aren’t built into apache by default. Change your cflags appropriately and try building the entire apache with the appropriate switches, and I believe you will find it works.

Unfortunately, the try/catch semantics introduce additional overhead that aren’t warrented unless the module author (you) intends to use them, so Apache is not built that way by default.

Na gut, ich geb mich also geschlagen und werde den Apache neu bauen

Gruss, Marc