Access Violation - Unknown Run-Time error : 210

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
laz847
Beiträge: 114
Registriert: Mi 18. Jun 2014, 16:39

Access Violation - Unknown Run-Time error : 210

Beitrag von laz847 »

Hallo zusammen, wie einige evtl. noch wissen, suche ich in meinem Projekt eine sporadisch auftretende AV. Viele von Euch haben mir bereits geholfen meinen Code zu verändern bzw. zu verbessern, die Access Violation ist allerdings immer noch da :D :evil:. Ich habe meine Software am 13.04 neu gestartet, es folgte nach einigen Stunden Laufzeit ein Absturz genau an diesem Tag, leider war das Programm komplett beendet also konnte ich nichts mehr in meinem Log-Memo sehen. Also habe ich die exe neu erstellt, ich habe nur die Zusatzfunktion ebenfalls in ein Textfile zu loggen hinzugefügt.

Dann am 13.04 neu gestartet, die exe lief bis gestern (20.04) also volle 7 Tage x 24h ohne Probleme durch, dann kam gestern die Av erneut. Leider habe ich versehentlich das Logfile beim Neustart überschrieben, war aber nicht so schlimm die AV kam einige Stunden später gleich nochmal.

Das erkläre ich so genau weil meine Software in 10 Threads immer wieder das Gleiche macht. Die 10 Threads importieren Daten, führen mit diesen Berechnungen durch und zeigen die Ergebnisse an, dieser Vorgang dauert pro Thread ca. 200 ms und startet dann erneut.

Mir stellt sich als erstes die Frage: Warum kommt die AV manchmal mehrmals am Tag aber wie zuletzt auch mal 7 Tage gar nicht?

Ich habe den Arbeitsteil im Thread.Execute in einen Try-Except Block gefasst:

Code: Alles auswählen

try while not(Terminated) do begin
 .... [work] ....
 except
  on E : Exception do
  log(GetLastError() , 'THREAD EXCEPTION | ClassName ' + E.ClassName + ' | Message ' + E.Message + ' | ' , ftid);
 end; 
Dabei wurde nun folgendes geloggt:

>> 10|21.04.2015|09:43:17|THREAD EXCEPTION | ClassName Exception | Message Unknown Run-Time error : 210 |
>> 8|21.04.2015|09:43:17|THREAD EXCEPTION | ClassName Exception | Message Unknown Run-Time error : 210 |

Wie man hier sehen kann haben 2 Threads eine Exception ausgelöst, Thread 8 und 10.
210 Object not initialized
When compiled with range checking on, a program will report this error if you call a virtual method without having called its object’s constructor.
http://www.freepascal.org/docs-html/user/userap4.html

When compiled with range checking on <<<<<< habe ich zur Fehlersuche

Auf der folgenden Seite gibts ebenfalls Hinweise zu 210: http://wiki.freepascal.org/User_Changes_Trunk
implementation changes
Exception type for object reference checking changed
Old behaviour: When object reference checking (-CR or {$OBJECTCHECKS ON}) is enabled and the unit SysUtils is used then an exception of class Exception with localizeable message Unknown runtime error 210 is created.
New behaviour: Now an exception of class EObjectCheck with localizeable message Object reference is Nil is created.
Reason: All other runtime errors in the 2xx range have appropriate exception types, so it is only natural to have an explicit type for runtime error 210 as well.
Remedy: If your code previously checked an exception for the message Unknown runtime error 210 you should now check for the exception class EObjectCheck.
"if you call a virtual method without having called its object’s constructor."

Wie gesagt meine Threads tun immer dasselbe, mir ist nicht klar welche virtuelle Methode ich da plötzlich nutzen soll, ohne den Constructor genutzt zu haben?

Ich übergebe mir beim jedem Logeintrag GetLastError() und logge diesen ebenfalls mit wenn er <> 0. Dabei fiel mir auf das immer wieder "GetLastError() : 5 | Zugriff verweigert." geloggt wird.

Meine Fragen:

1. Wie kann ich mehr Infos zur EXCEPTION bekommen, mit "Unknown Run-Time error : 210" komm ich nicht wirklich weiter.

2. GetLastError() loggt mir dauernd "GetLastError() : 5 | Zugriff verweigert" und das auch obwohl und während die Software einwandfrei läuft, wie komme ich da an mehr Infos?


Wie immer riesen DANKE an Euch!
Zuletzt geändert von laz847 am Di 21. Apr 2015, 13:14, insgesamt 2-mal geändert.

Benutzeravatar
theo
Beiträge: 10858
Registriert: Mo 11. Sep 2006, 19:01

Re: Access Violation - Unknown Run-Time error : 210

Beitrag von theo »

Dann hast du irgendwas nicht sauber gemacht.
Prüfe deinen Code nochmal auf potenziell gleichzeitige/unzeitige Zugriffe etc.

Meine grundsätzliche Einstellung dazu habe ich dir schon mal mitgeteilt:
theo hat geschrieben:Ich persönlich verwende Multi-Threading nur, wenn es nicht anders geht.
Warum sollte ich ohne Not
- Die Komplexität erhöhen?
- Neue Fehlerkategorien ermöglichen?
- Das Debugging erschweren?

laz847
Beiträge: 114
Registriert: Mi 18. Jun 2014, 16:39

Re: Access Violation - Unknown Run-Time error : 210

Beitrag von laz847 »

Meine grundsätzliche Einstellung dazu habe ich dir schon mal mitgeteilt:
Ja und ich teile diese Einstellung, wenn es nicht nötig ist, sollte man auf Threads verzichten. In meinem Projekt sind sie meiner Meinung nach jedoch nötig, da ich wie bereits beschrieben bestimmte Berechnungen gleichzeitig erledigen, Dinge in einem Chart anzeigen lassen und die Rechenlast auf 4 Kerne verteilen möchte.
Dann hast du irgendwas nicht sauber gemacht.Prüfe deinen Code nochmal auf potenziell gleichzeitige/unzeitige Zugriffe etc.
Hab ich geprüft bzw. prüfe ich seit Monaten, da ich ein Client - Server Prinzip nutze, in welchem die Daten per MemoryMappedFiles übertragen werden, sind diese per Mutex geschützt. Sollte da irgendetwas schief laufen müsste mir eigentlich entweder der Client oder der Server zumindest irgendeine Meldung ausgeben.

Die Software arbeitet perfekt, sie macht genau was sie soll und alles läuft wunderbar, bis diese AV das Programm abstürzen lässt. Es sind wie gesagt ca. 11000 Zeilen Code, es muss doch möglich sein die Ursache mittels Logging + Debugging zu lokalisieren, ich stochere total im Dunkeln und weiß nicht wo ich anfangen soll zu suchen?

Kannst Du mir in dieser Richtung evtl. weiterhelfen?

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Access Violation - Unknown Run-Time error : 210

Beitrag von Michl »

Aus genau dem gleichen Grund habe ich mir eine recht performante Log-/Status-Klasse geschrieben (In Potenzen schneller, als Ausgabe auf der Console). Sie schreibt immer mit, was welcher Thread macht. Diese läuft selber in einem Thread und kommuniziert mit einem Externen Programm (per SimpleIPC), was diese Log-/Status-Texte speichert oder wenn gewünscht darstellt. Eine Urform dieser Klasse hatte ich hier im Forum mal vorgestellt, diese ist aber weit weg, von dem, wie sie zur Zeit aussieht. Leider habe im Moment zu viele Baustellen, um sie in einen vorzeigbaren Zustand zu bringen, steht aber noch auf meiner ToDo-Liste. Weitere Infos, wenn gewünscht.

Mir hat auf jeden Fall dieser Text geholfen: http://wiki.freepascal.org/Logging_exce ... call_stack

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Access Violation - Unknown Run-Time error : 210

Beitrag von Michl »

Ach ja zur Fehlersuche noch der Hinweis, wie ich da vorgehen würde:

Projektkopie zur Fehlersuche erstellen, in dieser alles definitiv nicht Fehlerverursachende herausschmeißen und laufen lassen.
Von dieser Kopie wieder eine Kopie erstellen, die weiter vereinfacht wird (z.B. nur Rechenoperationen oder nur das Erstellen der Threads testen usw.)
Solange vereinfachen, bis ein möglicher Fehler ersichtlich wird.

Möglichst auch mal Extrem-Tests von der Art und Weise machen, wie du Threads erstellst und wieder frei gibst.
etc.

Diese Diskussion in der Mailing-List fand ich mal ganz interessant und zum Thema passend: http://comments.gmane.org/gmane.comp.co ... eral/36037

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

laz847
Beiträge: 114
Registriert: Mi 18. Jun 2014, 16:39

Re: Access Violation - Unknown Run-Time error : 210

Beitrag von laz847 »

Hi Michl, die Seite kenne ich, trotzdem danke!

Ich war mir nur nicht sicher ob mir die Ausgaben dann auch Infos liefern mit denen ich etwas anfangen kann? Aber Ihr ja evtl...

Code: Alles auswählen

procedure DumpExceptionCallStack(_tid:Byte; E: Exception);
var
  I: Integer;
  Frames: PPointer;
  Report: string;
begin
  Report := 'Program exception! ' + LineEnding +  'Stacktrace:' + LineEnding + LineEnding;
  if E <> nil then begin
    Report := Report + 'Exception class: ' + E.ClassName + LineEnding +  'Message: ' + E.Message + LineEnding;
  end;
  Report := Report + BackTraceStrFunc(ExceptAddr);
  Frames := ExceptFrames;
  for I := 0 to ExceptFrameCount - 1 do Report := Report + LineEnding + BackTraceStrFunc(Frames[I]);
  log(GetLastError() , 'EXCEPTION REPORT | ClassName ' + E.ClassName + ' | Message ' + E.Message + LineEnding + Report , _tid);
end;
 
// im execute dann:
 
try while not(Terminated) do begin
 .... [work] ....
 except
  on E : Exception do begin
   log(GetLastError() , 'THREAD EXCEPTION | ClassName ' + E.ClassName + ' | Message ' + E.Message + ' | ' , ftid);
   DumpExceptionCallStack(ftid , E);   
  end;
 end;
Hab die DumpExceptionCallStack mal mit reingenommen, mal sehen was da drinsteht wenn die AV das nächste Mal kommt, kann aber wie gesagt Stunden oder Tage dauern :(.

DANKE!
Solange vereinfachen, bis ein möglicher Fehler ersichtlich wird.
Mache ich gerade, habe schon ziemlich viele Routinen ausgebaut und momentan laufen nur noch die "Grundfunktionen" und genau in einer von denen muss das Problem liegen. Ist halt nur schwierig irgendetwas festzustellen, wenn es auch mal 4-5-6 Tage fehlerfrei läuft obwohl das Problem nicht lokalisiert bzw. behoben wurde.

Hat evtl. jemand eine Idee wie ich aus GetLastError() mehr rausbekommen? Ich bekomme die 5 (Zugriff verweigert) obwohl alles funktioniert und keine Fehler angezeigt werden. Wenn ich alles richtig verstanden habe ist GetLastError() Thread bezogen, es könnten also theoretisch auch unterschiedliche Fehler in verschiedenen Threads gleichzeitig in GetLastError() sein?

edit : Thread Safety of String >> :cry: ich gucke mir mal meine Strings nochmal an :cry:
Zuletzt geändert von laz847 am Di 21. Apr 2015, 14:25, insgesamt 1-mal geändert.

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Access Violation - Unknown Run-Time error : 210

Beitrag von Michl »

laz847 hat geschrieben:edit : Thread Safety of String >> :cry: ich gucke mir mal meine Strings nochmal an :cry:
:shock:

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

Benutzeravatar
theo
Beiträge: 10858
Registriert: Mo 11. Sep 2006, 19:01

Re: Access Violation - Unknown Run-Time error : 210

Beitrag von theo »

laz847 hat geschrieben:wenn es nicht nötig ist, sollte man auf Threads verzichten. In meinem Projekt sind sie meiner Meinung nach jedoch nötig,
Aus dieser Meinung würde ich erst einmal eine Gewissheit machen.
Wenn alles am Schluss doch durch den Flaschenhals "grafische Anzeige" muss, sind Zweifel angebracht.
Ich würde u.U. sogar gewisse Abstriche bei der Geschwindigkeit in Kauf nehmen zu Gunsten eines stabilen und wartbaren Systems.

laz847
Beiträge: 114
Registriert: Mi 18. Jun 2014, 16:39

Re: Access Violation - Unknown Run-Time error : 210

Beitrag von laz847 »

Ich würde u.U. sogar gewisse Abstriche bei der Geschwindigkeit in Kauf nehmen zu Gunsten eines stabilen und wartbaren Systems.
Würde ich auch, nur sind die Berechnungen so aufwändig, dass ich das nacheinander nicht in einer annehmbaren Zeit schaffe. Und im Optimierungsbetrieb bin ich mit 4 Kernen schneller als mit einem, aber wie gesagt da müsste ich Dich wesentlich tiefgehender informieren was da passiert und warum. Ich will eigentlich gar nicht so doll abschweifen, um Dir das genau zu erklären müsstest Du Dich mit einigen komplett anderen Themen näher beschäftigen. Willst Du das überhaupt :? ?
Wenn alles am Schluss doch durch den Flaschenhals "grafische Anzeige" muss, sind Zweifel angebracht.
Nein, im Chart werden immer nur die Results aus 1 der Threads angezeigt, die anderen 9 führen zwar dann ihre Berechnungen durch, geben aber im Chart nichts aus, welchen man sehen will wählt man manuell. Die Chartausgabe ist auch nicht das Ziel der Software, sie dient nur zur Visualisierung + Prüfung. Das ganze Projekt würde komplett ohne Chart auskommen, primär geht es um die Berechnungen die dort durchgeführt werden.

------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

Hab jetzt mal mit dem GetLastError() 5 "Zugriff verweigert" angefangen, dieser hat überraschenderweise gar nichts mit Threads oder meinem Projekt zu tun!? Ich lasse in einem sonst leeren Beispiel in einem Timer GetLastError() loggen, alle 100ms.
21.04.2015|16:34:29|GetLastError() 5 | Zugriff verweigert.
21.04.2015|16:34:30|GetLastError() 5 | Zugriff verweigert.
21.04.2015|16:34:30|GetLastError() 1400 | Ung?ltiges Fenster-Handle.
21.04.2015|16:34:30|GetLastError() 5 | Zugriff verweigert.
21.04.2015|16:34:31|GetLastError() 5 | Zugriff verweigert.
21.04.2015|16:34:31|GetLastError() 5 | Zugriff verweigert.
21.04.2015|16:34:31|GetLastError() 5 | Zugriff verweigert.
21.04.2015|16:34:31|GetLastError() 5 | Zugriff verweigert.
21.04.2015|16:34:32|GetLastError() 1400 | Ung?ltiges Fenster-Handle.
21.04.2015|16:34:32|GetLastError() 5 | Zugriff verweigert.
21.04.2015|16:34:33|GetLastError() 1400 | Ung?ltiges Fenster-Handle.
21.04.2015|16:34:33|GetLastError() 1400 | Ung?ltiges Fenster-Handle.
21.04.2015|16:34:34|GetLastError() 1400 | Ung?ltiges Fenster-Handle.

Das kommt schon, wenn ich die Software + den Timer starte und dann nur den Schieber auf der Trackbar hin und her bewege, ist das bei Euch auch so?

Beispielprojekt im Anhang, vielen Dank!
getlasterror check.zip
(126.19 KiB) 134-mal heruntergeladen
Vermutlich ist das auch wieder irgendein Problem mit meinem OS (Qubes + Xen + Wine)?

Benutzeravatar
theo
Beiträge: 10858
Registriert: Mo 11. Sep 2006, 19:01

Re: Access Violation - Unknown Run-Time error : 210

Beitrag von theo »

laz847 hat geschrieben: Das kommt schon, wenn ich die Software + den Timer starte und dann nur den Schieber auf der Trackbar hin und her bewege, ist das bei Euch auch so?
Nö, kein Problem hier. Getestet als 64bit Windows Executable unter Wine.
Lazarus 1.5 r48574M FPC 3.1.1 x86_64-linux-gtk 2
Linux 3.16.7-7-desktop / openSUSE 13.2 (Harlequin) (x86_64)
wine-1.7.28
laz847 hat geschrieben: Vermutlich ist das auch wieder irgendein Problem mit meinem OS (Qubes + Xen + Wine)?
Wenn man alle Wurmbüchsen auf einmal aufmacht, dann krabbelt's halt überall raus. :wink:

Michl
Beiträge: 2511
Registriert: Di 19. Jun 2012, 12:54

Re: Access Violation - Unknown Run-Time error : 210

Beitrag von Michl »

Also ich kann dieses Verhalten bestätigen, ich bekomme auch diese Meldungen, wenn ich die Trackbar eine Weile bewege. Windows 7 64bit, Lazarus 1.5 r48762M FPC 3.1.1 r30612 i386-win32-win32/win64

EDIT: Die Meldungen gibt es, wenn man mit der gedrückten Maustaste über die Scrollbar hinaus fährt - ist also absolut unbedenklich! :roll:

Code: Alles auswählen

type
  TLiveSelection = (lsMoney, lsChilds, lsTime);
  TLive = Array[0..1] of TLiveSelection;  

laz847
Beiträge: 114
Registriert: Mi 18. Jun 2014, 16:39

Re: Access Violation - Unknown Run-Time error : 210

Beitrag von laz847 »

Ach was, beide Meldungen "Zugriff verweigert" und "Ungültiges Fensterhandle"?

Unter Linux Mint läuft das Testprogramm (das ja wirklich nur aus einem Formular, Memo, Trackbar und Timer besteht) gar nicht, bzw. kann man die exe mit Wine starten, es erscheint auch ein Eintrag in der Taskleiste aber die Form ist nicht sichtbar. Auch Minimieren oder Maximieren macht sie nicht sichtbar. Mein Projekt, das wesentlich umfangreicher ist läuft unter Mint. Solche Sachen machen mich immer etwas ängstlich :( ....

Ich hatte bisher nur die Exceptions von den WorkerThreads abgefangen:

Code: Alles auswählen

try 
 while not(Terminated) do begin
  // [work]
 end;
except
 on E : Exception do begin
  log('WORKER THREAD EXCEPTION'
   + ' | ClassName ' + E.ClassName
   + ' | UnitName '  + E.UnitName
   + ' | Message '   + E.Message
   , ftid);
  MyDumpExceptionCallStack(ftid , E); // << ftid 1-10
 end;
end;                         
 
Dank Michl's Tipp/Link habe ich nun auch die Exceptions des Mainthreads abgefangen, habe mich zuvor immer auf die Workerthreads konzentriert, sieht aber so aus als wenn der MainThread die Exception auslöst?

Code: Alles auswählen

procedure Tevo_form.CustomExceptionHandler(Sender: TObject; E: Exception);
begin
 log('MAIN THREAD EXCEPTION'
  + ' | ClassName ' + E.ClassName
  + ' | UnitName '  + E.UnitName
  + ' | Message '   + E.Message
 , 0);
 MyDumpExceptionCallStack(0 , E); // << MyDumpExceptionCallStack(thread id 0-10 , E); 0 main , 1-10 worker
end;
 
procedure Tevo_form.FormCreate(Sender: TObject);
begin
 Application.OnException := @CustomExceptionHandler;
end; 
Guckt mal was ich hier hab :D (da freut man sich schon über Exceptions ;))
0|22.04.2015|14:13:49|MAIN THREAD EXCEPTION | ClassName EListError | UnitName Classes | Message List index (259) out of bounds
0|22.04.2015|14:13:49|THREAD EXCEPTION REPORT | ClassName EListError | UnitName Classes | Message List index (259) out of bounds
------------------------------------------------------------------------------------------------------
Program exception!
Stacktrace:

Exception class: EListError
Message: List index (259) out of bounds
$004622EF
------------------------------------------------------------------------------------------------------
0|22.04.2015|14:13:52|
Dazu mal wieder eine grundsätzliche Frage von mir, was passiert mit Exceptions wenn KEIN "CustomExceptionHandler" existiert?

Verstehe ich das richtig, wenn ich die Exceptions so wie ich es jetzt mache abfange, im MainThread und in den WorkerThreads sollte es doch eigentlich nie zu einem kompletten Absturz der Software kommen können oder? Durch die Exceptionbehandlung sollten diese nun zwar gemeldet und geloggt werden, dass Programm läuft dann jedoch weiter oder? Bedeutet im Umkehrschluss, habe ich keine Exceptionbehandlung führt eine Exception unweigerlich zum Absturz bzw. Ende des Programms?

Habe mein Projekt 2 x laufen, einmal über den Debugger unter Qubes und einmal nur die exe unter Linux Mint. Unter Mint werden dieselben Exeptions geloggt, unter Qubes stoppt der Debugger mit einer Messagebox die man erst wegklicken muss. Was mir fehlt sind genauere Infos, Zeilennummer, Listenname usw..., wie komme ich da weiter?

In den Projekteinstellungen sind alle Überprüfungen aktiv, Optimierung auf 0, -gl ist gesetzt und -Xs ist nicht gesetzt, Debugging-Info ist auf Dwarf mit Sets.

DANKE!

Antworten