Autor Beitrag
Tobi482
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 135



BeitragVerfasst: Di 15.01.08 19:47 
Hi Leute,

mein Problem begegnet mir jetzt schon das zweite Mal in völlig verschiedenen Projekten. Es muss irgendwas mit dynamischen Arrays zu tun haben.

Am besten fange ich erstmal an zu erzählen^^

Ich habe ein Programm, das läuft wie ich es mir erhofft habe, ohne irgendwelche Fehler.

Nun habe ich dieses Programm um eine "Logging Funktion" erweitern. Es handlet sich dabei um einen separaten Thread der alle 10 Min Daten aus der Software ausliest und diese speichert.

Bei den Daten handelt es sich um Vektoren und Vermessungsdaten einer Messsonde. Je länger die Sonde läuft, desto mehr Messdaten kommen an.
Dabei liegt mein Interesse nicht an den Daten gemessen über der Zeit, sondern am gesamten Spektrum.

Ich frage also nicht ab Funktion(Zeitpunkt):Messwert, sondern Funktion(Messwert):Zeitpunkt.

Daher liest der Thread alle bereits gemessenen Daten ein und fügt immer nur dann Datensätze hinzu, wenn ein noch nicht gemessener Wert gemessen wurde.

Sobald ich den Thread starte kommt es nach einiger Zeit zu Fehlern.
Dabei handlet es sich meistens um Fehler wie "Stack überlauf" oder einfachste Funktionen AUßERHALB des Thread stürzen ab.

Wie kann eine Funktion, die immer problemlos funktionierte, Probleme verursachen nur weil ein Thread gestartet wurde?
z.B. diese hier, sie erzeugt irgendwelche Fehler (das Parameter String wird ja in wirklichkeit als Pointer übergeben. Dieser Pointer soll in einen ungülitigen Speicherbereich zeigen)
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
//Wandelt einen HexString in einen String um
Function HexStrToStr(Text:String):String;
var
     i         : Integer;
begin
     Result := '';

     While Length(Text) <> 0 do
     begin
          Result := Result + chr(StrToInt('$' + Text[1] + Text[2]));
          Delete(Text, 1, 3);
     end;
end;


Ich habe darauf hin angefangen den Thread zu untersuchen, irgendwas in ihm muss falsch sein. Ich habe den "bösen Teil" des Threads bereits gefunden, finde darin aber keine Fehler.

Plötzlich erinnerte ich mich an ein Problem, was mich vor einem halben Jahr dazu bewogen hat, ein Projekt abzubrechen, da ich mit meinem Latein am Ende war.

Es waren die gleichen unerklärlichen Fehler wie heute (Der Teufel steckt im Detail)

Wenn ich im Thread die Dynmaischen Arrays auskommentiere, läuft alles problemlos. Zum gleichen Schluss bin ich auch vor einem halben Jahr gekommen.

Entweder habe ich ein tief sitzendes Verständnisproblem mit diesen Arrays oder sie sind einfach verbugt wie früher die Streams auch.

Fragen:

Kann man dynamische Arrays in einen "packed record" einbinden?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
Type
     TTRecord = packed record
          Datum        : TDateTime;
          Daten        : Array of TTDatensatz;
     end;

Sind dynmaische Arrays in einem Record über einen Record-Pointer ansprechbar?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
Type
     TTRecord = packed record
          Datum        : TDateTime;
          Daten        : Array of TTDatensatz;
     end;
     pTTRecord = ^TTRecord;

     //...

     SetLength(pTTRecord^.Daten, 10);
     High(pTTRecord^.Daten);
     pTTRecord^.Daten[i].Messwert := 0;

Können solche Record mit dynmaischen Arrays durch New und Dispose verwaltet werden?
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
     var   pData : pTTRecord;

     New(pData);

     SetLength(pData^.Daten, 10);
     High(pData^.Daten);
     pData^.Daten[i].Messwert := 0;


Soblad auch nur wenigen Zeilen mit den dynmaischen Pointern benutzt wreden kommt es früher oder später zum crash.

Bin für jede Hilfe Dank und möchte mich schonmal im vorraus dafür bedanken.

Mit freundlichen Grüßen
Tobi
Xion
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
EE-Maler
Beiträge: 1952
Erhaltene Danke: 128

Windows XP
Delphi (2005, SmartInspect), SQL, Lua, Java (Eclipse), C++ (Visual Studio 2010, Qt Creator), Python (Blender), Prolog (SWIProlog), Haskell (ghci)
BeitragVerfasst: Mi 16.01.08 10:07 
Hi,

Vermutung: TTDatensatz ist eine Klasse.

Wenn ja:
Du musst diese Klasse via FreeAndNil(Datensatz[x]) wieder wegräumen, falls du die Größe des Arrays veränderst, sonst gibts irgendwelche Speicherleichen (stack overflow).

Ansonsten:
von packed arrays hab ich keine Ahnung :nixweiss:

Xion

_________________
a broken heart is like a broken window - it'll never heal
In einem gut regierten Land ist Armut eine Schande, in einem schlecht regierten Reichtum. (Konfuzius)
hazard999
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 162

Win XP SP2
VS 2010 Ultimate, CC.Net, Unity, Pex, Moles, DevExpress eXpress App
BeitragVerfasst: Mi 16.01.08 11:32 
Hallo,

ich hatte mal vor längerer Zeit auch so ein Problem.

Bei mir hats daran gelegen wie Delphi strings verarbeitet im Zusammenhang mit dem MemoryManager der OutOfTheBox bei Delphi 6 dabei warst.

Wenn du deine HexStrToStr-Routine mit sehr großen Strings aufrufst, kann der Code zu einer fürchterlichen Speicherfragmentierung führen.

Die Auswirkungen können dann stark varieren (StackOverflow, OutOfMemoryExceptions...).

Folgender Vorschlag:

1. Funktionen verwenden die OutOfTheBox dabei sind (HexToBin)
2. StringListen statt strings verwenden (Besseres Speichermanagement)
3. Keine Löschung im string vornehmen, sondern immer nur die Zeichen rauskopieren die du brauchst

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
Function HexStrToStr(Text:String):String;
var
     i         : Integer;
begin
     Result := '';
     i := 1;

     While i <= Length(Text) do
     begin
          Result := Result + chr(StrToInt('$' + copy(Text, i, i + 2));
          i := i + 2;
     end;
end;


bzw

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
Function HexStrToStr(Text:String):String;
var
     i         : Integer;
     strl : TStringList;
begin
     strl : TStringList.create;
     Result := '';
     i := 1;

     While i <= Length(Text) do
     begin
          strl.Add(chr(StrToInt('$' + copy(Text, i, i + 2)));
          i := i + 2;
     end;
     result := stringReplace(strl.Text,#13#10,'',[rfReplaceAll, rfIgnoreCase]);
     strl.Free;
end;


r u

René

_________________
MOV EAX, Result;MOV BYTE PTR [EAX], $B9;MOV ECX, M.Data;MOV DWORD PTR [EAX+$1], ECX;MOV BYTE PTR [EAX+$5], $5A;MOV BYTE PTR [EAX+$6], $51;MOV BYTE PTR [EAX+$7], $52;MOV BYTE PTR [EAX+$8], $B9;MOV ECX, M.Code;MOV DWORD PTR [EAX+$9], ECX
Tobi482 Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Beiträge: 135



BeitragVerfasst: Di 29.01.08 14:19 
Hab ganz vergessen diesen Thread zu beenden
Danke nocheinmal für eure Hilfe

PS: Es waren echt sehr lange Strings^^ habe nun deinen Vorschlag benutzt und es funktioniert alles^^ DDANNKKEKE :)

Mit freundlichen Grüßen
Tobi