TFPGMap mit StringList

Für Fragen zur Programmiersprache auf welcher Lazarus aufbaut
Antworten
mtbf40
Beiträge: 72
Registriert: Do 3. Nov 2011, 16:39

TFPGMap mit StringList

Beitrag von mtbf40 »

Hallo,

wer kann hier mal helfen?

ich habe folgenden Code:

Code: Alles auswählen

xml_ver_Rec = record
    enabled  : String;      //for Base Versions
    patches  : TStringList;
end;
TMap_xml = specialize TFPGMap<String, xml_ver_Rec>;
.
.
.
var
  xmlMap  : TMap_xml; //Key/Value Map - Base Version, xml_ver_Rec;
  xmlR    : xml_ver_Rec;
  
  
procedure TForm1.FormCreate();
Begin
        .
        .
   xmlMap       := TMap_xml.Create;
   xmlR.patches := TStringList.Create;
        .
        .
End;
 
procedure TForm1.read_xml(doc: xmlDocPtr; nChild: xmlNodePtr);
Begin
        .
        .
        patchL kommt aus einem Dictionary
        xmlR.enabled := enabProp;
        
    while Assigned(child) do
    begin
      Pver := child^.PROPERTIES^.CHILDREN^.content;

      Debug_outp(IntToStr({$I %LINENUM%}), 'DEBUG', 'check Patch Version from XML '+Pver);

      for i:=0 to patchL.patches.Count -1 do
      begin
        //compare Patch Version from xml with Patch Version from Registry (patchL List)
        if Pver = patchL.patches[i] then
        begin
          Penabled := child^.PROPERTIES^.NEXT^.CHILDREN^.content;
          xmlR.patches.AddPair(Pver,Penabled);
          child := child^.NEXT^.NEXT;
        end
        else
        begin
          Debug_outp(IntToStr({$I %LINENUM%}), 'WARN', 'Patch Version from Registry '+patchL.patches[i]+' not in xml '+Pver);
          Penabled := 'true';
          xmlR.patches.AddPair(Pver,Penabled);
        end;
      end;
      xmlMap.Add(baseProp,xmlR);
      Debug_outp(IntToStr({$I %LINENUM%}), 'DEBUG', 'xmlR Patch '+xmlR.patches[0]);

      xmlR.patches.Free;
      xmlR.patches            := TStringList.Create;
      xmlR.patches.Duplicates := dupIgnore;
      xmlR.patches.Sorted     := true;

      if NOT Assigned(child) then Break;
      child := child^.NEXT^.NEXT;
    end;
        .
        .
End;

Das Problem ist jetzt, dass im xmlMap.Add(baseProp,xmlR.patches[0]) nichts abgespeichert wurde.

Mathias
Beiträge: 6210
Registriert: Do 2. Jan 2014, 17:21
OS, Lazarus, FPC: Linux (die neusten Trunk)
CPU-Target: 64Bit
Wohnort: Schweiz

Re: TFPGMap mit StringList

Beitrag von Mathias »

Ich vermute mal, das hast nur den Zeiger auf den String gespeichert, anstelle des Strings selbst.
Brauchst du zwingend "specialize" um einen Record zu speichern ?
Mit Lazarus sehe ich grün
Mit Java und C/C++ sehe ich rot

schoschy
Beiträge: 26
Registriert: Di 18. Okt 2022, 15:46

Re: TFPGMap mit StringList

Beitrag von schoschy »

auf die xml_ver_Rec greifst du mit xmlMap.Data[n] zu.

wp_xyz
Beiträge: 4895
Registriert: Fr 8. Apr 2011, 09:01

Re: TFPGMap mit StringList

Beitrag von wp_xyz »

Ich habe mich jetzt nicht so in den Code hineinvertieft, dass ich sagen könnte, ich würde alles verstehen. Aber mir fällt auf, dass die StringListe ein Element des xml_ver_rec Records ist, der in der FPGMap gespeichert wird. Da würde ich erwarten, dass jeder Record in der Map eine eigene StringListe hat, es würde ja auch gar keinen Sinn machen, dieselbe Information immer wieder abzuspeichern. Aber diese StringListe wird nur 1-mal erzeugt, im OnCreate-Ereignis des Formulars. Das sieht für mich seltsam aus, es "müffelt" auch nach drohendem Crash, wenn am Ende die Map-Elemente freigegeben werden und dieselbe StringList immer wieder zerstört wird (oder hast du an das Freigeben der patches-StringListe noch gar nicht gedacht?)

shokwave
Beiträge: 471
Registriert: Do 15. Nov 2007, 16:58
OS, Lazarus, FPC: Win11/Ubuntu Budgie (L 3.0 FPC 3.2.2)
CPU-Target: i386, x64
Wohnort: Gera

Re: TFPGMap mit StringList

Beitrag von shokwave »

@wp_xyz: Doch, das macht er, am Ende der While-Schleife.

Ist nur geraten, da man nicht sieht wo der Fehler auftritt, aber das sieht für mich nach dem Fehler aus. Die Objekte der StringListen("patches"), sollten doch erst freigegeben werden, wenn man nicht mehr darauf zugreifen will.

Ich lese den Code so:
1.für patches Speicher reservieren(onCreate)
In der While-Schleife dann:
2.Daten reinschreiben
3.Speicher freigeben (und damit Daten löschen)
4.neuen Speicher reservieren
wieder zu 2.

Das patches.free sollte meiner Meinung nach erst passieren, wenn der record aus der map gelöscht wird.

@mtbf40: Ich gehe mal davon aus, dass der Debug_outp noch korrekt ist.
mfg Ingo

wp_xyz
Beiträge: 4895
Registriert: Fr 8. Apr 2011, 09:01

Re: TFPGMap mit StringList

Beitrag von wp_xyz »

shokwave hat geschrieben:
Do 5. Okt 2023, 18:21
@wp_xyz: Doch, das macht er, am Ende der While-Schleife.
Richtig, hab ich nicht gesehen. Und da wird auch eine neue Instanz angelegt. Aber ich meine jetzt, dass eine Instanz zuviel angelegt wird: eine in FormCreate und eine am Ende jedes Durchlaufs; die letzte vor dem Break erzeugte Instanz enthält keine Daten zugewiesen.
shokwave hat geschrieben:
Do 5. Okt 2023, 18:21
Das patches.free sollte meiner Meinung nach erst passieren, wenn der record aus der map gelöscht wird.
Genau. Das patches.Free muss hjier weg, das ist das Problem

mtbf40
Beiträge: 72
Registriert: Do 3. Nov 2011, 16:39

Re: TFPGMap mit StringList

Beitrag von mtbf40 »

Hi,

ich habe es jetzt so gelöst

Für den Record nutze ich jetzt eine Klasse.
Diese wird in FormCreate instanziiert.

Code: Alles auswählen

   xml_igxl_ver = class
   Public
    enabled : String;
    patches : TStringList
  end;
und dann erstelle ich für jeden Run eine neue Instanz von der Klasse und der Patch Liste

Code: Alles auswählen

    //reset Structures for next run (IGXL Version)
    xmlR                    := xml_igxl_ver.Create;
    xmlR.patches            := TStringList.Create;
    xmlR.patches.Duplicates := dupIgnore;
    xmlR.patches.Sorted     := true;
Da es alles Pointer sind, muss ja immer eine neue Instanz erstellt werden, sonst würde man die Werte immer überschreiben.
Das funktioniert jetzt...

Nochmals danke für die Hilfe - das nächste Problem steht schon vor der Tür... :( - kommt aber in einem neuen Thread

Antworten