Files |  Tutorials |  Articles |  Links |  Home |  Team |  Forum |  Wiki |  Impressum

Aktuelle Zeit: Fr Jul 18, 2025 11:49

Foren-Übersicht » Programmierung » Allgemein
Unbeantwortete Themen | Aktive Themen



Ein neues Thema erstellen Auf das Thema antworten  [ 42 Beiträge ]  Gehe zu Seite 1, 2, 3  Nächste
Autor Nachricht
BeitragVerfasst: Mi Sep 21, 2005 12:53 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Also mein Programm leidet an nem schweren Zeigerfehler. Plötzlich, zufällig und absolut nicht nachvollziebar tauchen Fehler in Codestücken auf die seit einem halben jahr und länger fehler frei funktionieren. Z.B. hatte ich mal den Fall, dass bei einer eifachen Stringzuweisung (aString := 'Das ist der Text') eine Accessviolation kam.

Da (ich glaub Lossey wars) schonmal jemand im Forum sowas erwähnt hatte, und die Indizien eindeutig sind, glaube ich, dass ein Zeiger mir mein Programm versaut.

Nun erstmal ne einfach Frage zu anfang:

Ich hab ne TList. In der sind Zeiger auf Strings, Integers und was weis ich alles abgelegt. Alle Pointer sind mit new() erzeugt worden. D.h. ich muss die auch wieder freigeben. Jetzt stellt sich mir die Frage, ob dispose(Liste[i]) immer funktioniert, oder ob ich erst den Pointer typisieren muss. Ich meine damit z.B. das:
Code:
  1. pInt : ^Integer;
  2.  
  3. pInt := Liste[1];
  4. dispose(pInt);


Bisher hab ich einfach die gesammte Liste per dispose(List[i]) gesäubert.

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Zuletzt geändert von Flash am Mi Sep 21, 2005 15:56, insgesamt 1-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 15:15 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Hmmm. Kann mich erinnern so etwas ähnliches gesagt zu haben. Macht aber nichts. Das mit dem Gedächtnis ist bei mir eh so ne Sache für sich. ;-)

Ja die Fehler sind hässlich. Lass dich nicht davon verleiten wo die Fehler auftauchen. Das wird zu 99% der Fälle nur eine Folgeerscheinung sein. Der wirkliche Fehler wird wo ganz anders liegen.

Bis vor 3 Monaten hätte gesagt, dass es genügt Dispose(List[Idx]) aufzurufen. Aber ich wurde eines besseren belehrt. Wenn du einen Pointer auf ein Record freigibst in dem sich ein String befindet, dann wird dieser nicht freigegeben. Du musst den Pointer erst einmal typisiert aus der Liste holen und dann frei geben. Ich weiß nicht ob das mit Pointern auf Strings auch so ist. Also lieber erst mal rausholen.

Wobei sich mir auch die Frage stellt warum du die Pointer überhaupt gemischt hast? Das ist nicht gerade ungefährlich. Und warum du so minimale Pointer wie Integers ablegst? Da gibt es definitiv andere Möglichkeiten.

Sonst kann ich dir nur raten an jede Stelle bei der du Pointer verwendest peinlich genau zu achten, dass alles richtig ist. Dann nach Möglichkeit nur gleiche Typen in eine Liste packen. Ich deferenziere grundsätzlich immer, auch wenn delphi das eigentlich tut. Irgendwann macht es das nicht mehr und man spricht die Adresse des Pointers an. Wenn du Pointer nicht mehr benötigst die aber irgendwo noch liegen und evtl. verwendet werden könnten. Dann immer auf nil setzen. Zwei Pointer auf den selben Inhalt solltest du auch vermeiden. Nach Möglichkeit sollte es eine Stelle geben die Pointer erstellt und nicht weit davon entfernt sollten diese wieder freigegeben werden. Alle anderen sollten diese Pointer nur benutzen. Also Create und Destroy einer Klasse oder so etwas. Also nicht Klasse A erstellt sie und Klasse xyz gibt sie wieder frei.

Du solltest auch auf jeden Fall mal mit MemProof an die Sache ran. Wichtig. Schalte TD32 Debuginfos an. Dann siehst du sogar genau wo etwas flöhten geht.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 15:47 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Nun die Pointer auf integere brauch ich, weil ich in einer Liste (TList) Infos abspeicher. Da kommt z.B. Immer ein String, gefolgt von 3 Int. Da ich das weiß, kann ich mir dadraus ne Ausgabe bauen. Nachdem ich das gesehen hab geb ich die Daten wieder frei.

Ich glaub ich hab sogar irgendwo einen Pointer auf ein Record in ner Liste...ich guck gleich mal ob ich dort was finde. EDIT: Nö...der wird typisiert freigegeben.

Ich hab noch ganz andere ausgefallene Probleme (http://forum.dsdt.info/viewtopic.php?t=26883)

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 16:08 
Offline
DGL Member
Benutzeravatar

Registriert: Do Dez 05, 2002 10:35
Beiträge: 4234
Wohnort: Dortmund
Also für solche Strukturen solltest du dir ein Record machen und in diesem Record echte Werte speichern und dann den Pointer des Record in die Liste legen. Ist viel Effizienter und nicht so fehleranfällig. Wenn du mehrere unterschiedliche Records in die Liste packen möchtest empfehle ich die Daten in eine Klasse zu packen. Dann kannst du eventuelle Funktionalität mit verknüpfen und du kannst deren Typ abfragen. Somit entstehen keine Verwecselungen mehr. Da Klassen bereits auch Pointer sind ist es noch kompfortabler damit zu arbeiten und langsamer wird es dadurch auch nicht.


Zu dem anderen Fehler. Hier mal ein Stück Code von einem TForm. Lässt sich auf alle Klassen ummünzen. Und das funktioniert so auch. So mache ich das auch ständig. Wenn du das genau so hast, es aber nicht geht, dann hast du bei dir irgend ein anderes Problem. Was ich nicht ganz nachvollziehen kann.

Code:
  1. type
  2.   TForm1 = class(TForm)
  3.   private
  4.   public
  5.     destructor Destroy; override;
  6.   end;
  7.  
  8. implementation
  9.  
  10. destructor TForm1.Destroy;
  11. begin
  12.   // Mach was
  13.  
  14.   inherited;
  15. end;


Typecasting auf Klassen zum Freigeben sind überflüssig, da der Destruktor virtuell ist und somit ab TObject aufgerufen werden kann. Wenn du zum Beispiel recht langlebige Variablen auf Klassen hast und die Instanzen aber frei gegeben wurden, dann solltest du diese auch auf nil setzen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 18:20 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Ist das Typcasting auch dann überflüssig, wenn ich eine abgeleitete Klasse in einer Variable verstecke und die dann freigebe?

Ist das beides das selbe?:
Code:
  1.  
  2. var bclass : TBaseClass;
  3.  
  4. bClass := TAbgeleitet.Create;
  5.  
  6. //Variante1
  7. bClass.Free;
  8.  
  9. //Variante2
  10. TAbgeleitet(bClass).Free;

Wird bei beiden TAbgeleitet.Destroy aufgerufen?

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 18:23 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Ja, TObject.Free ruft automatisch Destroy auf. Aber dafür muß man den Destruktor immer mit override deklarieren. Ansonsten gibt es auch eine Warnung.
Bei .Net gibt's auch .Free, aber das ruft Dispose auf, falls das Objekt IDispose implementiert. Man kann also .Free auch mit ganz normalen .Net Klassen, wie z.B. dem FileStream verwenden.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 18:35 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Ich hätte gedacht, dass das erste Free, nur TBaseClass.Destroy aufruft.
Free merkt also, welche Klasse das ist?

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 18:40 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Destroy ist schon in TObject virtuell. Daher wird immer der Destructor Destroy aufgerufen, der zu dem aktuellen Objekt gehört. So wie bei normalen virtuellen Methoden auch.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 19:09 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Memproof zeigt mir 43 Fehler an... :shock:
Aber keienr davpn wirkt sich sichtbar aus....hm...

ladt mir jetzt nochmal MemCheck. Mal sehn was da so rauskommt.

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 20:11 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Das ist z.B. ein Hauptgrund für .Net. Solche Überlegungen und Fehler gibt's da nämlich so gut wie gar nicht mehr.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 21:56 
Offline
DGL Member
Benutzeravatar

Registriert: Mi Aug 17, 2005 13:19
Beiträge: 98
Wohnort: Jahnsdorf
LarsMiddendorf hat geschrieben:
Das ist z.B. ein Hauptgrund für .Net. Solche Überlegungen und Fehler gibt's da nämlich so gut wie gar nicht mehr.

Was hat .NET mit diesem Problem zu tun? Wenn Flash eine Lösung in .NET gewollt hätte, hätte er das gesagt. Außerdem brauch man keinen GC, der eh immer dann eingreift, wenn man's eh nicht gebrauchen kann. Wenn man richtig programmiert erübrigt sich ein GC sowieso. Also bitte: .NET-Fraktion bitte Klappe halten, wenn Ihr nicht gefragt seit! Das ging mir auch am 16.08. tierischst auf die Nerven!

Gut, jetzt zum Thema:
Versuch am Besten bei Variant-Nachbauten auf jegliche Typen mit Compiler-Magic in der Speicherreservierung (Dyn. Arrays, Strings, ...) zu verzichten und nutze Alternativ Statische Arrays mit (eigener) dynamischer Größen-Reservierung sowie PChars. Dann kannst Du damit effektiv Probleme der VCL ausschließen (die in solchen Dingen relativ buggy ist.

Versuche außerdem mal den Aufruf von "Finalize" bei String-Variablen (wenn schon unbedingt nötig), obwohl das Dispose IMHO sowieso machen müsste.

_________________
Administrator of Project Omorphia
Bild


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 22:43 
Offline
DGL Member

Registriert: Do Apr 08, 2004 16:55
Beiträge: 516
BenBE hat geschrieben:
LarsMiddendorf hat geschrieben:
Das ist z.B. ein Hauptgrund für .Net. Solche Überlegungen und Fehler gibt's da nämlich so gut wie gar nicht mehr.

Was hat .NET mit diesem Problem zu tun? Wenn Flash eine Lösung in .NET gewollt hätte, hätte er das gesagt. Außerdem brauch man keinen GC, der eh immer dann eingreift, wenn man's eh nicht gebrauchen kann. Wenn man richtig programmiert erübrigt sich ein GC sowieso. Also bitte: .NET-Fraktion bitte Klappe halten, wenn Ihr nicht gefragt seit! Das ging mir auch am 16.08. tierischst auf die Nerven!


Kein Grund Unfreundlich zu werden!

Sein Beitrag war durchaus Sinnvoll, und es ist auch nicht verboten auf irgendetwas hinzuweissen!
Und wieso bitte Greift der GC immer dann ein wenn man ihn nicht braucht?? Er läuft nebenbei als eigener Thread und verursacht keinerlei Probleme und sorgt für einen flüssigen Programablauf!
Selbst wenn man zu den besten Programmierern gehört vergisst man manchmal etwas! Warum also nicht .NET benutzen. Der GC nimmt einem nicht nur schreibarbeit ab!
Wenn es dir auf die Nerven geht brauchst du nicht zu kommen, .NET gehört definitiv zum Thema Crossplatform, und wenn es dir nicht passt brauchst du nicht zu kommen!

_________________
Shareholder und Leitender Entwickler bei Pipedream-Games.

Zitat: Siehst du diesen Park da unten? Jeden Tag lernen sich darin Menschen kennen und verlassen einander. Und du hast dein ganzes Leben Zeit darin zu gehen.


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 22:44 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Zitat:
Was hat .NET mit diesem Problem zu tun? Wenn Flash eine Lösung in .NET gewollt hätte, hätte er das gesagt.

Flash programmiert neuerdings hauptsächlich, mal von diesem Bsp. abgesehen in C++. Das bedeutet, dass er seine Programme ohne Änderung(mit Zeigern und allem) mit Visual C++/CLI für .Net kompilieren kann. Insofern zumindest als Option für die Zukunft erwähnenswert. Und manche Dinge erwähne ich gerne. Gibt ja andere Leute die ständig von Cross-Plattform reden, was ich z.B. eher unwichtig finde. Da rege ich mich ja auch nicht immer auf.

Zitat:
Außerdem brauch man keinen GC, der eh immer dann eingreift, wenn man's eh nicht gebrauchen kann. Wenn man richtig programmiert erübrigt sich ein GC sowieso.

Jaja die richtigen Programmierer. Richtige Programmierer arbeiten mit Assembler oder besser gleich mit dem Hex-Editor.
Der GC ist nicht nur eine Annehmlichkeit und verhindert gleich eine ganze Menge an Fehlern (=> sichere Software) sondern die Belegung von Speicher ist schneller, da der (kleine) Heap bei jedem Durchgang zusammengeschoben wird und so der Speicher hintereinander, wie bei einem Stack belegt werden kann. Statt eines aufwändigen Suchens in der Liste der freien Blöcke, wird einfach der Zeiger für die Spitze des Heaps weitergeschoben und fertig.
Der GC greift nur dann ein wenn es nötig ist und sammelt auch nur so viel ein wie gerade eben nötig ist. Zudem wird das Verhalten dynamisch an das jeweilige Programm angepaßt, so dass ein manuelles Aufrufen eher schadet. Der große Heap kann je nach Konfiguration mehrere hundert MB belegen bevor eine vollständige Sammlung durchgeführt wird. Der Trick unter .Net ist nicht sinnlos Referenzen zu erzeugen (z.B. String direkt aneinander hängen) um den GC nicht unnötig zu beanspruchen.

Zitat:
Also bitte: .NET-Fraktion bitte Klappe halten, wenn Ihr nicht gefragt seit! Das ging mir auch am 16.08. tierischst auf die Nerven!

Am 16.09 meinst du wohl. Allerdings bist du bei mir an der falschen Addresse, da ich recht wenig zum Chat (~21:15 bis ~23:00 gar nichts) beigetragen habe und da ich mir das Log auch nicht angesehen habe, weiß ich auch gar nicht was du meinst.


Zuletzt geändert von LarsMiddendorf am Mi Sep 21, 2005 22:50, insgesamt 2-mal geändert.

Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 22:44 
Offline
Guitar Hero
Benutzeravatar

Registriert: Do Sep 25, 2003 15:56
Beiträge: 7810
Wohnort: Sachsen - ERZ / C
Programmiersprache: Java (, Pascal)
Zitat:
.NET-Fraktion bitte Klappe halten, wenn Ihr nicht gefragt seit!
:?
Ganz Egal wie deine Meinung zu dem Thema ist, so ein Ton ist bei DGL nicht erwünscht. Ich hoffe auch du hälst duch in Zukunft daran.
@Lars: Rein prinzipiell sind die Infos zu .Net für mich momentan belanglos.

@VCL=Buggy: Also die Wahrscheinlichkeit, dass ein Fehler in meinem Code von mir stammt ist gegenüber der Wahrscheinlich dass der Fehler von der VCL kommt ungefähr 1000000:1 . Ich hab schon vieles gesehn, aber das die Komponenten die ich nutze Fehler produzieren noch nie. Das schließ ich mal kategorisch aus. Mehr noch: Wer PChars verwendet brauch sich über sowas wie ich habe nicht zu beschwehren. String-Klassen sind wohl eine der besten erfindungen die OOP mit sich gebracht hat. Jeder der was anderes nutzt hat zu lange C programmiert. ;)

Compilermagic in form von PreProzessoranweisungen gibts net. Dynamische Arrays sind Vodoo und bei mir im Code schon lange nicht mehr gesichtet worden.

Ich schätze, es is ein ganz "normaler" Pointer der sich da verselbstständigt hat. Mal sehn, wo...

_________________
Blog: kevin-fleischer.de und fbaingermany.com


Nach oben
 Profil  
Mit Zitat antworten  
 Betreff des Beitrags:
BeitragVerfasst: Mi Sep 21, 2005 22:55 
Offline
DGL Member
Benutzeravatar

Registriert: Sa Dez 28, 2002 11:13
Beiträge: 2244
Nun gut.
Eine andere Sache, was ich mal früher ausprobiert hatte, war eine Art GC in Delphi. Und zwar kann man ja mittels RTTI zumindest die published Eigenschaften auslesen. Wenn man alle erstellen Objekte in einer Liste sammelt kann man dann von Zeit zur Zeit über den ganzen Graphen gehen und nachsehen welche Objekte noch erreichbar sind. Da man natürlich recht eingeschränkt Zugriff auf den Stack hat, hatte ich das so gemacht, dass einige zentrale Objekte dann als statisch registiert wurden und von denen aus dann der ganze erreichbare Objektgraph markiert wurde. Jedenfalls hat man dann zwar nicht die Geschwindigkeit von .Net, aber man ist sicher das nichts vergessen wurde.


Nach oben
 Profil  
Mit Zitat antworten  
Beiträge der letzten Zeit anzeigen:  Sortiere nach  
Ein neues Thema erstellen Auf das Thema antworten  [ 42 Beiträge ]  Gehe zu Seite 1, 2, 3  Nächste
Foren-Übersicht » Programmierung » Allgemein


Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 5 Gäste


Du darfst keine neuen Themen in diesem Forum erstellen.
Du darfst keine Antworten zu Themen in diesem Forum erstellen.
Du darfst deine Beiträge in diesem Forum nicht ändern.
Du darfst deine Beiträge in diesem Forum nicht löschen.
Du darfst keine Dateianhänge in diesem Forum erstellen.

Suche nach:
Gehe zu:  
  Powered by phpBB® Forum Software © phpBB Group
Deutsche Übersetzung durch phpBB.de
[ Time : 0.010s | 15 Queries | GZIP : On ]