AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Problem mit Speicher und Handle

Ein Thema von s.h.a.r.k · begonnen am 14. Mär 2008 · letzter Beitrag vom 8. Mär 2010
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#1

Problem mit Speicher und Handle

  Alt 14. Mär 2008, 09:30
Hallo,

und zwar habe ich im Moment ein seltsames Problem und ich komme nicht ganz drauf, wieso. Ich habe eine Anwendung und eine passende objektorientierte Datenschicht. Ich greife auf eine Oracle-Datenbank (Version 9.x) mit AnyDAC zu und baue somit die Datenstruktur im Hintergrund auf. Diese kann ich natürlich immer wieder erneuern (=> refresh). Die Anzeige der Daten handhabe ich mit einem VirtualDrawTree (Virutal Treeview)).

Nun ist es so, dass ich nach mehrmaligem aktualisieren der Daten den folgenden Fehler erhalte:
Code:
Im Projekt panda.exe ist eine Exception der Klasse EOSError mit der Meldung 'Systemfehler. Code: 1158.
Der aktuelle Prozess verwendet alle Handles der zulässigen Höchstanzahl für Window Managerobjekte' aufgetreten.
Ich beobachte auch, dass meine Anwendung nach dem Start ca 36MB (!!!) für sich beansprucht. Der Verlauf weiterhin schaut dann wie folgt aus:
Aktualisierung
1. -> 36MB
2. -> 38MB
3. -> 46MB
4. -> 48MB
5. -> 59MB
x. -> 59MB

Ich weiß leider nich genau, wo der Speicher "abhanden" kommt bzw nicht mehr freigegeben wird. Es wäre auch ein wenig viel Quelltext die komplette Datenstruktur als Code hier zu präsentieren. Fakt ist aber, dass genau nach der Datenbankabfrage der Speicher immer und immer steigt, d.h. ich denke, dass es an AnyDAC liegt, wobei ich es eben nicht verstehe. So schaut mein Code aus. Der Speicher müsste doch wieder freigegeben werden und dürfte doch nicht mehr werden?!
Delphi-Quellcode:
// Beispielcode
sql := 'SELECT * FROM test_table';
table := TADDatSTable.Create();
try
  // gekapselte Methode aufrufen
  if (FDatabase.execSQL(sql, table) then
    // do something
  else
    // do nothing...
finally
  FreeAndNil(table);
end;
Ich hoffe ihr könnt mir hier weiterhelfen!

Mit freundlichen Grüßen
der Hai
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#2

Re: Problem mit Speicher und Handle

  Alt 14. Mär 2008, 09:41
Es liegt erstmal nicht zwingend einen deinen Objekten.

Irgendwo in deinem Code oder in den verwendeten Komponenten oder aber auch in einem anderen laufenden Programm werden zu viele Handles (Pipe, Socket, Window, GDI, Event, Process....) verwendet.

Zitat:
The total number of open handles in the operating system is limited only by the amount of memory available to the operating system. However, a single process may have no more than 16,384 open GDI object handles. The per-process limit on kernel handles is 2^30. There is no per-process limit on user handles, but there is a systemwide limit of 65,536.
Aber wie man das rausbekommt, weiß ich grad nicht.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#3

Re: Problem mit Speicher und Handle

  Alt 14. Mär 2008, 10:07
Jetzt stellt sich für mich die Frage, ob der verwendete Speicherplatz eben etwas mit den verwendeten Handles zu tun hat. Ich habe nun auch das folgende herausgefunden:

Delphi-Quellcode:
var
  FCommand : TADCommand;
  table : TADDatSTable;
begin
  // ...
  table := TADDatSTable.Create;
  try
    // SQL-Abfrage
    FCommand.Open;
    FCommand.Define(table);
    FCommand.Fetch(table, True); // !!! Genau nach der Zeile "explodiert"
                                  // die Speichernutzung von 15MB auf 44MB
    FCommand.Close;
    // ...
  finally
    FreeAndNil(table); // ab hier sinkt Sie wieder auf 36MB
  end;
end;
Das Problem bei mir ist wohl, dass irgendwo Handles "verloren" gehen... Oder seh ich das falsch?
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#4

Re: Problem mit Speicher und Handle

  Alt 14. Mär 2008, 11:00
Ja, anscheinend fehlen irgendwo ein paar "CloseHandle"

Deinen Speicher (wie mißt du den überhaupt) dürfte das nicht direkt betreffen. Hinter den Handles stehen ja "Objekte" von Windows. Und letztenendes geht es ja bei der Fehlermeldung anscheinend nicht um die Größe, sondern um die Anzahl.

Dein Fetsch wird wahrscheinlich Daten aus der Datenbank in deinen Adressbereich (zu table) kopieren und hinterher gibt der Speichermanager nicht gleich alles wieder frei (also nicht an Windows zurück). Das ist ganz normal und unbedenklich.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#5

Re: Problem mit Speicher und Handle

  Alt 14. Mär 2008, 11:26
Ich schaue im Taskmanager nach, wie viel Speicher meine Anwendung belegt. Ich weiß, dass dieser das nicht immer unbedingt richtig anzeigt (bestes Beispiel: BDS), aber ich denke, dass es schon eine Richtlinie ist, die einigermaßen passt. Das mit dem Speicher, der nicht an Windows zurückgegeben ist, kenne ich und ist mir klar. Nur dachte ich bisher dass das etwas mit dem Handle-Fehler zu tun hat.

Nun stellt sich mir die Frage, ob nicht AnyDAC einen internen Bug hat oder ich nur etwas falsch mache

Rein für mein Verständis:
Wenn ich ein Object (TMeinObjekt, ist von TObject abgeleitet) erzeuge, dann zeigt ja ein Handle auf die Instanz davon. Wenn ich FreeAndNil() aufrufe wird die Instanz "gelöscht" (also, aus dem Speicher entfernt) und das Handle automatisch freigegeben, oder?
Delphi-Quellcode:
var
  obj : TMeinObjekt;
begin
  // Objekt(e) erzeugen
  obj := TMeinObjekt.Create();

  // Berechnungen, etc.
  obj.doSomething;

  // Objekt freigeben
  FreeAndNil(obj);
end
Oder wo genau wird ein Handle erzeugt bzw. gebraucht? Dass es eine systemweite ID ist für z.B. Anwendungen weiß ich.

Danke schon mal für deine Hilfe, bringst mich immer ein Stück weiter.
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.685 Beiträge
 
Delphi 2007 Enterprise
 
#6

Re: Problem mit Speicher und Handle

  Alt 14. Mär 2008, 11:30
Einfache Instanzen bekommen kein Handle, sondern nur solche Elemente, die in irgendeiner Weise von Windows bereitgestellt oder verwaltet werden. Dazu zählen z.B. Fenster (auch Buttons und Edits usw. sind so gesehen Fenster) und ein paar andere Dinge. Einfache Objekte aber haben da keinen Anteil dran.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#7

Re: Problem mit Speicher und Handle

  Alt 14. Mär 2008, 11:33
Hm, dann versteh ich aber nicht ganz, warum mir keine Handles mehr zur Verfügung stehen... Ich mache nur Datenbankabfragen. Klar habe ich eine Main-Form, allerdings sind da nicht all zu viele Komponenten drauf.
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Benutzerbild von sirius
sirius

Registriert seit: 3. Jan 2007
Ort: Dresden
3.443 Beiträge
 
Delphi 7 Enterprise
 
#8

Re: Problem mit Speicher und Handle

  Alt 14. Mär 2008, 13:07
Wenn du in Delphi ein Objekt erzeugst, bekommst kein Handle im Windows-Sinn, sondern einfach nur einen Instanzzeiger. Und der hat mit deinem Handleproblem nichts zu tun.

Wenn du ein "Objekt" (ein richtiges Objekt ist es nicht, aber so ähnlich) von Windows erzeugst, bekommst du ein Handle. Mit diesme Handle kannst du unter Windows spezielle funktionen ausführen. Beispielsweise bekommst du für einen Socket ein Handle. Dann kannst du Daten über dieses Socket (welches durch ein Handle identifiziert wird) ins Internet schicken.
Die Meisten Funktionen unter Windows laufen über Handles:
-Dateiarbeit
-Sockets
-Fenster
-Pipes
-Events
-Mutex/Semaphore
-Processe haben auch Handles
-Threads
Hinter jedem Handle in Windows verbirgt sich auch eine Struktur an Daten. Und je nach Typ des Handles kannst du bestimmte Funktionen mit dieser Struktur ausführen. Die Struktur (also die Daten) selber landen IHMO aber bei Windows und nicht in deinem Speicherbereich.

Deine Vermutung würde ich auch unterstützen. Da schein ein Bug in dieser Komponente zu sein. Versuch mal die Methode der Komponente heruaszufinden um den Fehler (allein mit dieser Methode; durch x-mal aufrufen bspw.) zu reproduzieren.


PS: Auch ich habe nur Vermutungen, aber etwas anderes fällt mir dazu nicht ein. Den Fehler selber hatte ich auch noch nie.
Dieser Beitrag ist für Jugendliche unter 18 Jahren nicht geeignet.
  Mit Zitat antworten Zitat
Benutzerbild von s.h.a.r.k
s.h.a.r.k

Registriert seit: 26. Mai 2004
3.159 Beiträge
 
#9

Re: Problem mit Speicher und Handle

  Alt 14. Mär 2008, 13:29
Nach einigem an Testen habe ich den Fehler gefunden. Und zwar hole ich dazu etwas weiter aus:

Im Taskmanager hat man die Möglichkeit sich mehrere Spalten anzeigen zu lassen, unter dem Tab Prozesse. Dort habe ich mir, wie im Screenshot (siehe Anlage) die Handles, Thread und Objekte, die eine Anwendung zurzeit benötigt anzeigen lassen. Nun bin ich dann mit dem Debugger durch meine Anwendung gegangen und habe nach dem Problem selbst gesucht, d.h. an welches Stelle nun das Problem auftritt. Hierbei war sehr auffällig, dass die Benutzerobjekte einen sehr großen Teil ausgemacht hatten. Und zwar handelte es sich bei mir um einen Timer. Dieser wurde beim Konstruktor eines Objekts erzeugt, dieser erhält auch ein Handle! Bei genau 10000 Timern, d.h. 10000 Benutzerobjekten war dann Schluss und es wurde die Exception geworfen. Die Handle-Zahl stieg dabei allerding nicht! (laut Task-Manager)

Mein Problem hierbei war das folgende: ich wollte eine MDI-Anwendung erstellen, d.h. für jedes Objekt sollte es möglich sein, ein MDI-Formular aufrufen zu lassen. Per eingebauten Timer sollte sich das Objekt, welches einem Datensatz in der Datenbank zugeordnet ist, dann sperren, d.h. sodass kein anderer User daran Daten ändern kann. Dies mache ich, indem ich alle 20 Sekunden einen Zeitstempel in die DB schreibe und diesen dann bei einem anderen User, welcher auf den Datensatz zugreift abfrage. Nun habe ich, wie schon erwähnt den Timer beim Konstruktor erzeugt und dann eben beim Öffnen des MDIs nur gestartet, ergo war das Timer-Objekt immer vorhanden. Dies hätte dann dazu geführt, das ab 10000 Datensätzen mein Programm abschmiert. Durch einen weiteren dummen Programmierfehler (ich habe die Timer nicht an der passenden Stelle freigegeben) bin ich dann erst auf das Problem gestoßen. Nun setze ich nicht mehr lediglich den Timer auf Enabled, sondern erzeuge ihn erst beim Erstellen des MDI-Forumlars und beschränkte die maximale Anzahl der geöffneten MDI-Forumlare, sodass ich dieses Problem umgehen kann. Eigentlich brauch ich keine Beschränkung, da 10000 eine recht große Zahl ist, aber ich habe ja noch andere Elemente, die auch Platz brauchen

Ich hoffe, ich habe nun alles passend erklärt! Wenn es noch Fragen oder Unklarheiten geben sollte, dann bitte melden.

PS: Wer Rechtschreibfehler findet darf sie behalten

[EDIT] Bild vergessen [/EDIT]

Mit freundlichen Grüßen
der Hai
Miniaturansicht angehängter Grafiken
screenshot_977.png  
»Remember, the future maintainer is the person you should be writing code for, not the compiler.« (Nick Hodges)
  Mit Zitat antworten Zitat
Medium

Registriert seit: 23. Jan 2008
3.685 Beiträge
 
Delphi 2007 Enterprise
 
#10

Re: Problem mit Speicher und Handle

  Alt 14. Mär 2008, 13:57
Es gibt imho entweder eine praktikable, oder sogar definierte Obergrenze an Timern die registrierbar sind. 10000 halte ich schon für überirdisch! Du solltest das Konzept überdenken, z.B. nicht für jedes Formular einen eigenen Timer, sondern nur einen für alle. Offene Formulare tragen sich in eine Liste ein, und der Timer geht die Liste durch und macht die DB Einträge. So dürfte ein Schuh draus werden. Aber 10k Timer sind... boah
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:06 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz