Herzlich Willkommen, lieber Gast!
  Sie befinden sich hier:

  Forum » C / C++ (ANSI-Standard) » Offenbar "access Violation" durch C++-exceptions

Forum | Hilfe | Team | Links | Impressum | > Suche < | Mitglieder | Registrieren | Einloggen
  Quicklinks: MSDN-Online || STL || clib Reference Grundlagen || Literatur || E-Books || Zubehör || > F.A.Q. < || Downloads   

Autor Thread - Seiten: > 1 <
000
26.07.2002, 23:32 Uhr
Cer



Guten Tag.

Ich kämpfe seit ca. einer Woche mit einem sehr seltsamen "Bug".

Ich benutze den Borland C++ Builder 5.5 Compiler 5.5.1 unter Windows (freecommandlinetools.exe). Das ist die kostenlose Kommandozeilen-Version des Compilers. Zum Debuggen benutze ich den ebenfalls kostenlos erhältlichen Turbo Debugger (td32.exe).
Quelle: Borland Homepage

Vorneweg: ich kann leider keinerlei Quellcode des Programms bereitstellen, da der Fehler nur bei vollständig vorhandenem Code auftritt, der allerdings viel zu groß ist, als dass ich ihn hier abdrucken könnte. Ich habe versucht, den Code auf das Wesentliche (Fehlerverursachende) zu verkürzen, aber - wie gesagt - dann tritt der Fehler nicht mehr auf.

Ich habe eine Klasse bot und eine Klasse netsock. Beide in separaten Modulen. Aus dem Hauptmodul (main.cpp mit main()) rufe ich die Memberfunktion login von bot auf. Die wiederum erstellt ein Objekt der Klasse netsock, deren Konstruktor die private Memberfunktion resolve aufruft.

resolve wirft eine Exception vom Typ netsock_err. Der Stack sollte bis catch (netsock_err err) in login zurückgespult werden, was seinerseits eine Exception vom Typ bot_err wirft.

Das Problem: bevor diese Exception mit catch (bot_err err) in main() gefangen wird, meldet mir Windows zwei Fehler durch eine Ungültige Seite in MAIN.EXE und einen dritten durch eine Schutzverletzung in KERNEL32.DLL.

Das alles wäre ja noch ganz spaßig, wenn ich mir nicht absolut sicher wäre, dass es nicht meine Schuld ist. Es sieht nach einem verrückten gewordenen Pointer aus, der ins Codesegment oder zumindest in nicht zum Programm gehörende Datensegmente schreibt; nur benutze ich bis dahin keinen einzigen Pointer.

Wenn ich mit dem -v Switch kompiliere ("Source level debugging" - ermöglicht es, auf Quellcode-Ebene zu debuggen) und das Programm dann laufen lasse (im Debugger sowie auf der Kommandozeile) läuft es fehlerfrei. Ohne -v spuckt der Debugger natürlich wenig Sinnvolles (Assembler-Source und ein paar tausend Register) aus, meldet aber irgendwann eine Access Violation.

Hm. Tja. Nachdem ich wirklich alles analysierte und probierte kam ich zu dem Schluss, dass es für dieses Verhalten nur zwei Gründe geben kann: entweder ist die Standardbibliothek fehlerhaft (ich benutze string, cout und Konsorten und ein paar C-STL Funktionen) oder ich habe das Thema Exceptions noch nicht ganz kapiert.

Edit: mit diesem Fehler könnte ich leben, wenn das Programm vorher bereits 12.000 Zeilen Code hinter sich hätte. Hier werden allerdings nur diese paar Funktionen aufgerufen und ein paar strings initialisiert/bearbeitet; keine weiteren Funktionsaufrufe irgendeiner exotischen API oder so. Es ist praktisch ein allgemeines Rahmenprogramm.

Danke für's Lesen.

P. S.: Warum tut [code] eigentlich dasselbe wie [cpp] und nicht das, was in der Hilfe/FAQ steht?
--
-C

Dieser Post wurde am 27.07.2002 um 00:01 Uhr von Cer editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
001
27.07.2002, 10:00 Uhr
Bruder Leif
dances with systems
(Operator)


Moin!

Benutzt Du Exceptions im Con- oder Destructor einer Klasse? Oder einer Funktion, die dort aufgerufen wird? Das mag der Borland-Compiler nämlich gar nicht...
--
Mit 40 Fieber sitzt man nicht mehr vor dem PC.
Man liegt im Bett.
Mit dem Notebook.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
002
27.07.2002, 11:45 Uhr
virtual
Sexiest Bit alive
(Operator)


@cer
Bei deiem Problem kann ich Dir vermutlich nicht helfen,w eil ich den Compiler icht habe, den du benutzt. Ich habe mich gefragt, ob du tatsächlich so Exceptions fängst:

C++:
catch (netsock_err err)


oder doch eher so

C++:
catch (netsock_err[b]&[/b] err)


Im letzteren Fall wird nämlich kein copyctor vond er Exception aufgerufen, was möglicherweise auch schon einen Unterschied macht.

@leif
Also wenn der Borland Compiler keine Exceptions im ctor abkann, dann ist es ein mieser Compiler. Anders siehts bei Exceptions im dtor aus: die sind ein ganz dickes NoNo und sollten eh vermieden werden. Ich hatte dazu mal ne andere Meinung, aber es ist tats. so das Exceptions im dtor dazu führen, daß es unmöglich ist, exceptionsicheren Code zu schreiben.
--
Gruß, virtual
Quote of the Month
Ich eß' nur was ein Gesicht hat (Creme 21)
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
003
27.07.2002, 13:57 Uhr
Bruder Leif
dances with systems
(Operator)


Moin!

Tja, daß im Destructor keine Exceptions erlaubt sind, ist klar. Das Problem mit Exceptions im Constructor hängt mit den VCL-Klassen zusammen. Normalerweise hat der Borland-Compiler damit keine Probleme, aber da die VCL eigentlich in Object Pascal programmiert ist und der Cpp-Compiler einige "Verrenkungen" anstellen muß, damit die kompatibel sind, sind (unter anderem) Exceptions im Constructor eine zumindest "wackelige" Angelegenheit... aber wie gesagt, nur bei VCL-Klassen.
--
Mit 40 Fieber sitzt man nicht mehr vor dem PC.
Man liegt im Bett.
Mit dem Notebook.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
004
27.07.2002, 17:26 Uhr
Cer



Hallo Leif und virtual.

Danke für eure Antworten.

Ich muss mich korrigieren: die Exception tritt weder im Kon- noch im Destruktor einer der beiden Klassen auf. Der Ablauf sieht also ungefähr so aus:

(Die Default-Konstruktoren der beiden Klassen sind praktisch leer. Es werden nur ein paar konstante Member initialisiert)

main() -> Objekt der Klasse bot wird konstruiert (Default-Konstruktor) -> bot::login() wird aufgerufen -> hier wird ein Objekt der Klasse netsock konstruiert (auch Default-Konstruktor] -> netsock::nconnect() wird aufgerufen -> aus dieser Funktion wird netsock::resolve() aufgerufen, wo die Exception auftritt.

Die Exceptions fange ich tatsächlich als Wert und nicht als Referenz, das allerdings auch nur aus Test-Zwecken, da ich zur Zeit C++ erst noch lerne. Ich hab's bereits mit Referenzen in allen catch-Statements versucht - macht keinen Unterschied.

Tja. Es scheint also auch nicht an den Copy-Konstruktoren zu liegen, was im Übrigen sehr seltsam wäre, denn die Klassen, die den Fehler anzeigen sind wirklich nicht komplex und der Compiler sollte damit umgehen können.

Die Destruktoren aller beteiligten Klassen (auch von bot_err und netsock_err, die ja mit der Wert-Übergabe ein paar Mal aufgerufen werden) sind frei von Exceptions. Und würde dort eine Exception auftreten, sollte es keine Access Violation geben sondern viel mehr einen Aufruf vom unexpected-Handler, der seinerseits terminate() aufruft.

Alles, was ich rausfinden konnte war, dass die Access Violation zwischen dem catch-Statement in bot::login() und jenem in main() auftritt. Also: bevor catch in main() überhaupt erreicht wird.

Was evtl. noch erwähnenswert ist: ich benutze sozusagen riesige try-Blöcke (praktisch der ganze Rumpf von main() befindet sich in einem solchen). Das ist alles nicht besonders hübsch oder praxisnah, aber eigentlich sollte es ok sein.

P.S.: Ich bin zwar C++-Anfänger, aber kein C-Anfänger mehr und wenn ich mir nicht so sicher wäre, keinen (möglicherweise typischen) Anfänger-Fehler gemacht zu haben, würde ich euch gar nicht damit belästigen.
--
-C

Dieser Post wurde am 27.07.2002 um 17:29 Uhr von Cer editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
005
27.07.2002, 18:50 Uhr
Bruder Leif
dances with systems
(Operator)


Moin!

Probier's mal testweise mit


C++:
catch(...)
{
   cout << "Abgefangen!" << endl;
}


Gibt's dann immer noch eine Zugriffsverletzung?
--
Mit 40 Fieber sitzt man nicht mehr vor dem PC.
Man liegt im Bett.
Mit dem Notebook.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
006
27.07.2002, 19:17 Uhr
Cer



Hallo, Leif.

Wenn ich ich statt catch (netsock_err err) testweise catch (...) in bot::login() benutze, ist alles in Butter. Ich werfe dort eine neue Exception vom Typ bot_err, die korrekt bis zum catch (bot_err err) in main() durchläuft.

Wenn ich bot::login() unverändert lasse und stattdessen das catch-Statement in main() gegen catch (...) austausche gibt's wieder die Access Violation.

Hum. Was mag das bedeuten? Offenbar hat der Compiler ein Problem beim Fangen von netsock_err? Ziemlich unpraktisch.

Hier die beiden _err-Klassen:
(netsock_err befindet sich im namespace net)


C++:
class netsock_err
{
public:
    const netsock_errnum n;

    netsock_err(const netsock_errnum nn)
        : n(nn)
    {
    }
};


Und:

C++:
class bot_err
{
public:
    const bot_errnum n;

    bot_err(const bot_errnum nn)
        : n(nn)
    {
    }
};


(netsock_errnum und bot_errnum sind enums)

Nichts Spektakuläres, eben. Dass man das ganze mit Vererbung machen sollte, weiss ich auch. Hätte ich auch längst gemacht, wenn ich nicht diese Fehler bei der Verwendung solch einfacher Klassen bekäme.

Danke für die Hilfe.
--
-C

Dieser Post wurde am 27.07.2002 um 19:22 Uhr von Cer editiert.
 
Profil || Private Message || Suche Download || Zitatantwort || Editieren || Löschen || IP
Seiten: > 1 <     [ C / C++ (ANSI-Standard) ]  


ThWBoard 2.73 FloSoft-Edition
© by Paul Baecher & Felix Gonschorek (www.thwboard.de)

Anpassungen des Forums
© by Flo-Soft (www.flo-soft.de)

Sie sind Besucher: