Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Algorithmen, Datenstrukturen und Klassendesign (https://www.delphipraxis.net/78-algorithmen-datenstrukturen-und-klassendesign/)
-   -   Seltsame string-artefakte... (https://www.delphipraxis.net/170798-seltsame-string-artefakte.html)

DelphiCreak 3. Okt 2012 18:44

Seltsame string-artefakte...
 
Nabend DP'ler,

ich bin vorhin auf ein seltsames Problem gestoßen, für dass ich weder eine Erklärung noch im entferntesten einen Lösungsansatz habe.

Kurze Beschreibung:
Ich arbeite an einer Unit, BildDateien nach OpenGL zu laden (ich weiß, gibts schon, benutze aber eine eigene FileSystem-Klasse auf die das ganze aufbaut, ist auch nicht der Punkt.)

Jedes Bild hat nun eine Prozedur Reload, die eben dafür sorgt, dass Bilder sich neu Laden bzw wenn sie durch eine Funktion erzeugt werden, sich neu erzeugen. Nun hab ich da stehen:
Delphi-Quellcode:
  //always regenerate functional images
  if @generatorFunc <> nil then
  begin
    Log.DPrintf('regenerating ' + imgName + '.' + #13#10);
    generatorFunc(self);
    Exit;
  end;
Wobei Log.DPrintf nichts anderes macht, als den gegebenen String in einen Log zu schreiben und auf einer sichtbaren Konsole darzustellen. Soweit so gut.
Doch anstatt dass ich im Log schön die einzelnen generierten Bilder untereinander stehen habe a la:

regenerating _default.
regenerating _white.
regenerating _black.

etc bekomm ich das folgende:


regenerating _default.

rege
rege
rege
regenerating _flat.

rege
rege
rege
rege
rege
rege
rege

Die Strings werden also abgeschnitten. Ich habs mir im Debugger mal angeschaut, da wurde anscheinend irgendwie der Konstante String 'regenerating ' überschrieben durch 'rege'#0#0#0(Unlesbares Zeichen)#0'ing _white'. Und es sind immer diese 5 Chars, die überschrieben werden, genau mit denselben Zeichen.

Nun zur eigentlichen Frage: Wie kann das Sein, wo kann das Herkommen?

himitsu 3. Okt 2012 19:14

AW: Seltsame string-artefakte...
 
Spontan würde ich sagen, daß du irgendwo (nicht in dem gezeigten Codestück) einen Buffer-Overrun hast, welcher dir diesen Speicher überschreibt/verschießt.


PS: (hat aber nichts mit deinem Problem zu tun)
Delphi-Quellcode:
  if Assigned(generatorFunc) then
  begin
    Log.DPrintf('regenerating ' + imgName + '.' + sLineBreak);

DelphiCreak 3. Okt 2012 19:23

AW: Seltsame string-artefakte...
 
Müsste so ein Fehler nicht bei aktivierter Überlaufs-/Bereichsprüfung auffallen? Oder gibt es generell eine andere Möglichkeit so einen Fehler zu entdecken außer alles durchzugehen? (Die Units die für die Bilder zuständig sind und damit in Frage kommen umfassen mittlerweile ~3000 Zeilen)

Vor allem da der String beim 5-6 mal Loggen wieder intakt ist...bei einem Buffer-Overrun müsste der String dann doch eigentlich dauerhaft zerstört sein oder nicht?

sx2008 3. Okt 2012 19:53

AW: Seltsame string-artefakte...
 
Delphi-Quellcode:
if Assigned(generatorFunc) then
begin
  Log.DPrintf('regenerating ' + imgName + '.' + sLineBreak);
  (*
   * auskommentiert um zu testen ob dies die Ursache ist
  generatorFunc(self);
  *)
end;

himitsu 3. Okt 2012 20:05

AW: Seltsame string-artefakte...
 
Sagen wir es mal so: In einigen Delphis wurde vergessen der Speicher, wo diese Konstanten liegen, schreibgeschützt zu laden.


Es gibt mehrere Tools (teilweise auch FastMM), welche beim Suchen helfen.

Was du aber selber ganz einfach machen kannst.
Delphi-Quellcode:
  if Assigned(generatorFunc) then
  begin
    S := 'regenerating ';
    Log.DPrintf(S + imgName + '.' + sLineBreak);
Erstmal schauen, ob der Fehler nun immernoch dort liegt.
Dann bis zu dem String gehn und
Delphi-Quellcode:
Pointer(S)
in die überwachten Variablen und dir den Wert kopieren.
Nun
Delphi-Quellcode:
string(derWert)
in überwachten Variablen.
Jetzt kannst du gemütlich rumdebuggen und schauen wann und wo sich dieser String verändert.

[edit]
Zitat:

auskommentiert um zu testen ob dies die Ursache ist
Theoretisch ja, aber man muß beachten, daß sich dabei Adressen verschieben können, da sich ja der Code verändert hat, womit dann der Fehler einfach nur woanders hingewandert sein kann.
- entweder ist da wirklich der Fehler drin und nun ist er weg
- oder es wird eventuell nur etwas Anderes überschrieben (bzw. es knallt, weil diese neue Stelle nicht überschreibbar ist)

DelphiCreak 3. Okt 2012 20:08

AW: Seltsame string-artefakte...
 
@sx2008: habe ich schon gemacht, habe schon fast alles (in diesem Teil des Projekts) auskommentiert, kein Unterschied...Das schwierige ist halt dass das Projekt aus 40+ Units besteht, welche alle im Moment verwendet werden, und es könnte jetzt natürlich sein dass der Fehler schon vorher vorhanden war, nur jetzt diese String-Konstante erst in dem Speicherbereich gelandet ist, der beim Buffer-Overflow korrupiert wird...

Ist da die Bereichs/Überlauf prüfung wirklich komplett sinnlos? Weil ich wirklich keine Ahnung habe wie ich bei dem Umfang des Projekts herausfinden kann, was jetzt eben diese eine Konstante verändert...

@himitsu: Die Idee hatte ich auch gerade, werd ich mich mal dranmachen.

Edit: Interessanterweise scheint das Ganze Computer-Abhängig zu sein...Ich hatte auf meinem Haupt-PC schon alles gemacht, von neu erzeugen, DCU's/.exe löschen, IDE neustarten, kein Unterschied.
Nun einmal auf meinem Laptop kompiliert, der Fehler tritt nicht mehr auf...

Edit2: habs jetzt mal so deklaritert:
Delphi-Quellcode:
var TS: String = 'regenerating ';

procedure noImage.Reload(checkPrecompressed: Boolean; force: Boolean);
var current: TTime;
begin
  //always regenerate functional images
  if Assigned(generatorFunc) then
  begin
    Log.DPrintf(TS + imgName + '.' + sLineBreak);
    generatorFunc(self);
    Exit;
  end;
und anscheinend wird der String beim Übergeben an die Log-prozedur zerschossen, der Inhalt von TS bleibt komplett unverändert...

himitsu 3. Okt 2012 20:21

AW: Seltsame string-artefakte...
 
Das ist DAS Problem mit fehlgeleiteten Speicheroperationen ... es kommt drauf an, wo etwas überschrieben wird.
(es gibt Stellen, da fällt es nicht auf, weil dieser Bereich garnicht/selten genutzt wird, bzw. weil es nur reservierter, aber derzeit ungenutzter Speicher ist)

Und natürlich ist es systemabhängig, denn jedes System ist unterschiedlich ... hier der eine Treiber, dort ein Andere,bzw. andere Hardware usw.
Theoretisch sind solche Systeme zwar dynamisch und arbeiten zufällig, aber ein Computer arbeitet ja nicht zufällig, womit sich tweilweise ein "statisches" (reproduzierbares) Verhalten ergibt.

DelphiCreak 3. Okt 2012 20:28

AW: Seltsame string-artefakte...
 
Ist denn Embaracardo's RAD Studio XE2 auch davon betroffen, dass Konstanten nicht schreibgeschützt sind?

Edit: Rein Logisch müsste jetzt ja die Prozedur _UStrCatN, die in ja in Delphi dafür zuständig ist, dass 2+ Strings miteinander verbunden werden fehlerhaft arbeiten, da die Variable ja sich im Inhalt nicht ändert, und bei der Log-Funktion der Falsche String ankommt...doch wie soll sowas passieren? Kann ja dann eigentlich nur passieren wenn ich irgendwo einen Pointer in den Bereich des RAM's habe, in dem diese Prozedur liegt, und dann irgendwas daran verändere...Bin grad ziemlich ratlos wie man sowas vernünftig debuggen soll...

Edit2: Das Problem liegt definitv dabei, dass ich irgendwie die _UStrCatN verändere...erst wenn diese Prozedur aufgerufen wird, kommen die String-Artefakte...

DelphiCreak 3. Okt 2012 21:25

AW: Seltsame string-artefakte...
 
Ich versteh die (Delphi) Welt nicht mehr...ich mein okay, höchstwahrscheinlich irgendwo ein Speicherleck/überlauf...

Habe das ganze jetzt allerdings wie folgt deklariert:

Delphi-Quellcode:
var TS: String = 'regenerating ';

procedure noImage.Reload(checkPrecompressed: Boolean; force: Boolean);
var current: TTime;
begin
  //always regenerate functional images
  if @generatorFunc <> nil then
  begin
    TS := 'regenerating ';
    Log.DPrintf('regenerating ' + imgName + '.' + sLineBreak);
    generatorFunc(self);
    Exit;
  end;
was natürlich unglaublich unschön ist. wollte einfach mal schauen, was mit String-Konstanten die direkt davor deklariert werden passiert...Und jetzt hat TS beim ersten Durchlauf den Korrekten Inhalt, erst wenn er beim Erzeugen der 2. (die Reihenfolge in der die Texturen generiert werden spielt keine Rolle, immer bei der, die als 2. Erzeugt wird) wird TS beim abarbeiten der Zeile


Delphi-Quellcode:
   TS := 'regenerating ';
wie oben beschrieben verändert...


Alle Zeitangaben in WEZ +1. Es ist jetzt 09:50 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