Willkommen auf myCSharp.de! Anmelden | kostenlos registrieren
 | Suche | FAQ

Hauptmenü
myCSharp.de
» Startseite
» Forum
» Suche
» Regeln
» Wie poste ich richtig?

Mitglieder
» Liste / Suche
» Wer ist online?

Ressourcen
» FAQ
» Artikel
» C#-Snippets
» Jobbörse
» Microsoft Docs

Team
» Kontakt
» Cookies
» Spenden
» Datenschutz
» Impressum

  • »
  • Community
  • |
  • Diskussionsforum
Exception trotz try-catch
PierreDole
myCSharp.de - Member



Dabei seit:
Beiträge: 49

Themenstarter:

Exception trotz try-catch

beantworten | zitieren | melden

Moin,

ich habe mir ein Open-Source-Projekt runtergeladen und bekomme da ab und zu eine Exception geworfen. Dachte, ich packe einfach an der Stelle einen try-catch Ausdruck und gut ist. Leider funktioniert das nicht. Da ich selber eigentlich sehr selten try-catch benutze, tue ich mir gerade etwas schwer das richtig zu setzen.

Der Ausnahmefehler kommt immer bei return a, ob mit oder ohne try.

Im Original sieht die Methode wie folgt aus:


public unsafe AnimDataFrame CalculateCurrentGraphic(ushort graphic)
        {
            IntPtr address = _file?.StartAddress ?? IntPtr.Zero;

            if(address != IntPtr.Zero)
            {
                IntPtr addr = address + (graphic * 68 + 4 * ((graphic >> 3) + 1));

                ref AnimDataFrame a = ref Unsafe.AsRef<AnimDataFrame>((void*)addr);

                return a;
            }

            return default;
        }

Das ist mein try-catch Versuch:


public unsafe AnimDataFrame CalculateCurrentGraphic(ushort graphic)
        {
            IntPtr address = _file?.StartAddress ?? IntPtr.Zero;

            if(address != IntPtr.Zero)
            {
                try
                {
                    IntPtr addr = address + (graphic * 68 + 4 * ((graphic >> 3) + 1));

                    ref AnimDataFrame a = ref Unsafe.AsRef<AnimDataFrame>((void*)addr);

                    return a;
                }
                catch(System.AccessViolationException e)
                {
                    System.Console.WriteLine(e.Message);
                    return default;
                }
            }

            return default;
        }

Ist das so richtig?

Edit:
Habe die Exception ganz vergessen.
Unhandled Exception: System.AccessViolationException: Attempted to read or write protected memory. Dann der Verweis auf die Zeile mit return a.
Dieser Beitrag wurde 1 mal editiert, zum letzten Mal von PierreDole am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16147

beantworten | zitieren | melden

Welche Exception bekommst Du? Nicht alle Exceptions kann man abfangen, zB MemoryExceptions.
Bitte Fehlermeldungen im Original posten, siehe [Hinweis] Wie poste ich richtig?
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
PierreDole
myCSharp.de - Member



Dabei seit:
Beiträge: 49

Themenstarter:

beantworten | zitieren | melden

Sorry, mein Edit und Dein Post haben sich überschnitten.

Wenn man MemoryExceptions nicht abfangen kann, gibt es dann wenigstens eine Möglichkeit zu überprüfen, ob auf jene Stelle im Memory gerade zugegriffen werden kann?
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1516
Herkunft: Düsseldorf

beantworten | zitieren | melden

Steht doch in der Doku: AccessViolationException Class (System)
private Nachricht | Beiträge des Benutzers
Palladin007
myCSharp.de - Member

Avatar #avatar-4140.png


Dabei seit:
Beiträge: 1516
Herkunft: Düsseldorf

beantworten | zitieren | melden

Zitat von PierreDole
Sorry, mein Edit und Dein Post haben sich überschnitten.

Wenn man MemoryExceptions nicht abfangen kann, gibt es dann wenigstens eine Möglichkeit zu überprüfen, ob auf jene Stelle im Memory gerade zugegriffen werden kann?

Die konkrete Stelle hilft dir nicht weiter, die .NET Runtime schaufelt doch immer hin und her - solltest Du das verhindern/umgehen, dann hast Du schon deinen Fehler
Und ich denke, Abt meint die OutOfMemoryException. Wann die geworfen wird, steht in der Doku und dann hat man nicht nur irgendeine Stelle im RAM.
Dieser Beitrag wurde 2 mal editiert, zum letzten Mal von Palladin007 am .
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16147

beantworten | zitieren | melden

Zitat von Palladin007
Und ich denke, Abt meint die OutOfMemoryException.
Der Abt meint mehrere Exceptions.
Alle Exceptions, die laut .NET auf einen "corrupted state" des Prozesses hinweisen, darunter AccessViolationException und OutOfMemoryException.. können nicht gefangen werden.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
PierreDole
myCSharp.de - Member



Dabei seit:
Beiträge: 49

Themenstarter:

beantworten | zitieren | melden

Habe ich das richtig verstanden, daß wenn ich das Attribut [HandleProcessCorruptedStateExceptions] hinzufüge, dann sollte die Exception gecatcht werden? Leider kann ich die Exception nicht ohne Weiteres rekonstruieren und überprüfen ob es jetzt klappt. Die wird einfach ab und zu geworfen.

Ist das so richtig?


[HandleProcessCorruptedStateExceptions]
        public unsafe AnimDataFrame CalculateCurrentGraphic(ushort graphic)
        {
            IntPtr address = _file?.StartAddress ?? IntPtr.Zero;

            if(address != IntPtr.Zero)
            {
                try
                {
                    IntPtr addr = address + (graphic * 68 + 4 * ((graphic >> 3) + 1));

                    ref AnimDataFrame a = ref Unsafe.AsRef<AnimDataFrame>((void*)addr);

                    return a;
                }
                catch(System.AccessViolationException e)
                {
                    System.Console.WriteLine(e.Message);
                    return default;
                }
            }

            return default;
        }
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16147

beantworten | zitieren | melden

Die Exception ist im Endeffekt ein Hinweis, dass Du womöglich einen Fehler beim Speicherzugriff hast.
Du solltest also die Ursache korrigieren, nicht die Exception.

HandleProcessCorruptedStateExceptions greift nur in NetFX Projekten. Der Prozess selbst bleibt aber "corrupt".
In .NET Core bzw. .NET 5 und höher gibts das Attribut auch; macht aber nichts. Existiert nur noch aus Kompatibilitätsgründen.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4182

beantworten | zitieren | melden

@PierreDole: Die Addressberechnung (bzgl. graphic) erscheint mir auch eigenartig, besonders graphic >> 3, was ja graphic / 8 bedeutet (ausmultipliziert kommt da m.E. (graphic * (68 + 1/2) + 4) heraus!?!).
private Nachricht | Beiträge des Benutzers
PierreDole
myCSharp.de - Member



Dabei seit:
Beiträge: 49

Themenstarter:

beantworten | zitieren | melden

@Abt:
Ja, das ist etwas komplizierter, als ich es anfangs beschrieben habe. Die eigentliche Ursache liegt in einem Plugin. Ohne das Plugin wurde die Exception nicht geworfen. Irgendwo beißen sich die beiden unter bestimmten Umständen. Nun, das Plugin ist einerseits auch open-source, andererseits hat es mehrere Hundert Klassen. Da die Exception auf den Client verweist, weiß ich nicht wo ich im Plugin suchen sollte. Alleine das Einlesen würde Wochen dauern, die Fehlersuche womöglich Monate.
Von daher ist es jetzt für mich das Naheliegendste die Exception zu umgehen, da die Methode eh nur zur Berechnung einer Amimation von Spielfiguren dient. Ich kann damit leben, wenn mal eine Figur eine Animation nicht mitmacht. Nur der Client sollte nicht dabei crashen.

@Th69:
Ehrlich gesagt: keine Ahnung. Mit Memory und Pointern habe ich mich noch nicht auseinandergesetzt. Ich weiß nur, daß der >>-Operator irgendwas mit verschieben bedeutet, aber ausrechnen und/oder überprüfen kann ich die Rechnung im Code nicht.
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4182

beantworten | zitieren | melden

Woher hast du denn diese Formel? Bist du dir bei der 68 sicher (oder soll es 64 heißen)?

Du kannst dir doch (zum Test) jedesmal die Adressen ausgeben lassen:


Console.WriteLine($"{graphic}: {addr}");
Dann weißt du zumindestens, bei welchen Werten es crasht (letzte Zeile der Konsolenausgabe).

Bei Unsafe-Programmierung mußt du dir aber 100%ig sicher sein (ist ja, also ob man direkt C oder C++ programmiert) - jeder Speicherzugriffsfehler führt zum Crash!
private Nachricht | Beiträge des Benutzers
PierreDole
myCSharp.de - Member



Dabei seit:
Beiträge: 49

Themenstarter:

beantworten | zitieren | melden

Ich habe das nicht programmiert, ich benutze es nur. Es ist ein open-source Client für das uralte Ultima Online, geschrieben in C#. ClassicUO nennt er sich und das Plugin, das ich dazu benutze, ist der ClassicAssist.
private Nachricht | Beiträge des Benutzers
Abt
myCSharp.de - Team

Avatar #avatar-4119.png


Dabei seit:
Beiträge: 16147

beantworten | zitieren | melden

Woher hast Du es denn dann, gib ma paar Infos und lass uns nich raten :-)
Speicherzugriffsfehler in Prozessen führen i.d.R. immer zum Crash, daher muss man sie vermeiden, bevor sie auftreten.
- performance is a feature -

Microsoft MVP - @Website - @blog - @AzureStuttgart - github.com/BenjaminAbt
private Nachricht | Beiträge des Benutzers
Th69
myCSharp.de - Experte

Avatar #avatar-2578.jpg


Dabei seit:
Beiträge: 4182

beantworten | zitieren | melden

OK, danke für den Github-Link. Die Formel scheint wohl richtig zu sein, sie wird ja 2x benutzt (in src/IO/Resources/AnimDataLoader.cs sowie src/Game/Managers/AnimatedStaticsManager.cs (hier sogar als / 8 geschrieben).
private Nachricht | Beiträge des Benutzers