Einzelnen Beitrag anzeigen

Sequitar

Registriert seit: 8. Jan 2016
74 Beiträge
 
Delphi 10.4 Sydney
 
#1

Custom Record Freigabe verkettete liste

  Alt 22. Apr 2021, 18:22
Ich habe versucht eine datenstruktur wie folgt aufzubauen, (records sind ja managed?)
Delphi-Quellcode:
    Pnum = ^Tlargenum;
 Tlargenum= Record
      Private
        FLength, Fchunkcount: Word;
        FNext: pmyrec;
        _ispositive: Boolean;

      Const
        _Chunkdigits = 10;

      Type
        Tdigit = 0 .. 9;

      Var
        FDigits: Array [0 .. _Chunkdigits - 1] Of Tdigit;
      Private
      
        Class Procedure Clear(Var A: Tlargenum); Static;
public
        Constructor Create(Avalue: Pchar);
        Procedure Free;
end
Da records keinen Destructor einführen habe ich die class procedure clear, welche rekursiv alles löschen soll:
Delphi-Quellcode:

 Constructor Tlargenum.Create(Avalue: Pchar);
    Var
      Digitindex: Integer;
    Begin
      Inherited;
      If Assigned(Avalue)
      Then
      Begin
        If Avalue = ''
        Then
          Create('0')
        Else
        Begin
          Fnext := Nil;
          // Clear;
          FLength := 0; // System.Length(Avalue);
          Fchunkdigitcount := 0;
          Digitindex := 0;
          // get sign
          _ispositive := Avalue^ <> '-';
          If Not _ispositive
          Then
            Dec(Flength);
          While Not(Avalue^ In ['0' .. '9']) And (Avalue <> Nil) Do
            Inc(Avalue);
          While Avalue^ <> #0 Do
          Begin
            FDigits[Digitindex] := Strtoint(Avalue^);
            Inc(Avalue);
            Inc(Digitindex);
            Inc(Fchunkdigitcount);
            Inc(Flength);
            If Digitindex = _Chunkdigits
            Then
            Begin
              New(Fnext);
              Fnext^ := Tlargenum.Create(Avalue);
              Flength := Flength + Fnext^.Flength;
              Break;
            End;
          End;
        End;
      End;
    End;

  Procedure Tlargenum.Free;
    Begin
      Clear(Self);
    End;
  Class Procedure Tlargenum.Clear(Var A: Tlargenum);
    Var
      Temp: Pnum;
      Adigit: Pbyte;
    Begin
      A._ispositive := False;
      A.FLength := 0;
      A.Fchunkdigitcount := 0;
      Fillchar(A.Fdigits, System.Length(A.Fdigits), 0);
      While Assigned(A.Fnext) Do
      Begin
        Temp := A.Fnext;
        A.Fnext := A.Fnext^.FNext;
        Dispose(Temp);
      End;
      // Fmath := Nil;
    End;
soweit sogut:
nun führe ich class operators ein:
Delphi-Quellcode:
 Class Operator Implicit(A: Tlargenum): String; Overload; // OK
        Class Operator Explicit(A: Tlargenum): Integer; Overload; // OK
        Class Operator Explicit(A: Tlargenum): Byte; Overload; // OK
        // Class Operator Explicit(A: String): Tlargenum; Overload;
        Class Operator Implicit(A: Uint64): Tlargenum; Overload;
        Class Operator Implicit(A: Int64): Tlargenum; Overload;
        Class Operator Implicit(A: String): Tlargenum; Overload;
Delphi-Quellcode:
Class Operator Tlargenum.Implicit(A: String): Tlargenum;
    // Var
    // Returnrec: Tlargenum;
    Begin
      Result := Tlargenum.Create(Pchar(A));
      // Result := Returnrec;
    End;

  Class Operator Tlargenum.Implicit(A: Tlargenum): String;
    Var
      I: Byte;
    Begin
      Result := '';
      I := 0;
      While I < A.Fchunkdigitcount Do
      Begin
        Result := Result + Inttostr(A.FDigits[I]);
        Inc(I);
      End;
      If Assigned(A.FNext)
      Then
        Result := Result + A.Fnext^;
    End;

  Class Operator Tlargenum.Explicit(A: Tlargenum): Integer;
    Begin
      // ok:
      Var
        Temp: Tlargenum;
      Temp := High(Integer);
      Try
        If A < Temp
        Then
          Result := Strtoint(A)
        Else
          Raise Eoverflow.Create('Cant be converted into integer type');
        // error
      Except
        On E: Exception Do
          Showmessage(E.Message)
      End;
      Temp.Free;
      { If A > High(integer)
        Then
        Raise Exception.Create('Number cannot be converted into byte');
        Result := Strtoint(A); }

    End;

  Class Operator Tlargenum.Explicit(A: Tlargenum): Byte;
    Begin
      Var
        Temp: Tlargenum;
      Temp := High(Byte);
      If A > Temp
      Then
        Raise Exception.Create('Number cannot be converted into byte');
      Result := Strtoint(A);
      Temp.Free;
    End;

  Class Operator Tlargenum.Implicit(A: Uint64): Tlargenum;
    Var
      Temp: String;
    Begin
      Temp := UInttostr(A);
      Result := Temp;
      // Result.FLength := Length(Temp);
      // Result._ispositive := True;
    End;

  Class Operator Tlargenum.Implicit(A: Int64): Tlargenum;
    Begin
      Result := Uint64(Abs(A));
      Result._ispositive := A >= 0;
    End;
Die jeweiligen Conversions werden korrekt durchgeführt, aber zb. implicit conversions wie

Delphi-Quellcode:
    Assert(X > '3000000000000000');//x is vom typ tlargenum, der string wird implizit umgewandelt
        Assert(X >= '3000000000000000');
führen zu leaks, da die impliziten records nie freigegeben werden.
Wie kann ich den speicher denn hier wieder sauber freigeben?
Danke
  Mit Zitat antworten Zitat