AnsiString verursacht Speicherlecks



  • Hallo an alle,

    ich habe vor längerer Zeit etwas sehr merkwürdiges festgestellt. Ich habe mir mal eine Funktion geschrieben, die mir aus einen char-String einen Teilstring als AnsiString zurückliefert:

    AnsiString __fastcall CStr(char *s, int len) 
    { 
        return len ? AnsiString(s).SubString(1,len) : AnsiString(s);
    }
    

    Diese Funktion läßt sich ohne Fehler und Warnungen übersetzen. Die Funktionalität ist auch in Ordnung, aber bei jedem Aufruf wird ein Speicherleck hinterlassen. Wers nicht glaubt, sollte das einfach mal ausprobieren, der Fehler tritt unter CB5 und CB6 auf.

    Natürlich läßt sich das auch so lösen:

    String str = String(s,len);
    

    aber ich wußte das damals noch nicht, und bei Testläufen bin ich dann auf dieses Phänomen gestoßen.
    Vielleicht weiß ja jemand Rat, woher der Fehler stammen könnte. Und gleichzeitg soll das auch eine Information sein, was man beim CB unbedingt vermeiden sollte.

    Gruß Burkhard



  • Burkhi,
    also ehrlich gesagt, habe ich da Zweifel:

    1. Woher weißt Du, daß memory leaks entstehen?
    2. Was übergibst Du denn an die Funktion? Ein kurzes aber komplettes Beispiel, welches das Problem reproduziert, bringt vielleicht etwas Licht ins Dunkel ...


  • dschensky schrieb:

    <Fullquote gelöscht>

    Hallo,
    na sicher gebe ich dir mal ein Bsp:
    - Erzeuge eine neue Anwendung, die einen timer benutzt (mehr brauchst du nicht).
    - Setze das Timerinterval auf 10.
    - Gib den Code unten ein:

    AnsiString __fastcall CStr(char *s, int len)  
    {  
        return len ? AnsiString(s).SubString(1,len) : AnsiString(s); 
    }
    
    void __fastcall TForm1::´Timer1Timer(TObject *Sender)
    {
        static char *test = "Speicherfresser";
    
        Caption = CStr(test,8);
    
    }
    

    Mach doch dann bitte folgendes:
    - Starte das programm
    - Schau im Taskmanager unter Prozesse nach und such nach Projekt1.exe (oder wie du das profekt genannt hast), und du wirst sehen, wie schön gemächlich die Speichernutzung zunimmt.
    Das läßt sich jederzeit reproduzieren, bei mir nimmt die Speichernutzung ca. alle 2 sek um 4KB zu.

    Gruß Burkhard

    Edit:
    Zitate bitte auf das Notwendigste beschränken. Danke!



  • Burkhi,

    Burkhi schrieb:

    Das läßt sich jederzeit reproduzieren, bei mir nimmt die Speichernutzung ca. alle 2 sek um 4KB zu.

    also bei mir (Win2000, BCB4) bewegt sich da gar nichts. Memproof hat auch nichts auszusetzen.
    Bei den Seitenfehlern zappelt es ab und zu. Aber das hat ja nichts mit Speicher-Leaks zu tun.



  • Hallo dschensky ,

    na dann hab ich ja die Gewissheit, das ab dem CB5 da wohl etwas fehlerhaft ist, vermutlich ist es die AnsiString-Klasse.
    Wie ich ganz oben schon geschrieben hatte, tritt das unter CB5 und CB6 auf. Mit dem CB4 hatte ich das nicht getestet.

    Gruß Burkhard



  • Burkhi,

    Burkhi schrieb:

    na dann hab ich ja die Gewissheit, das ab dem CB5 da wohl etwas fehlerhaft ist, vermutlich ist es die AnsiString-Klasse.

    ich habe es im CB6 auch reproduziert - hätte ich nicht gedacht. Ich habe es nochmal etwas reduziert:

    for (int i = 1; i <= 1000; i++)
    {
        i ? String("1").SubString(1,0) : String("");
    }
    

    Nimmt man den SubString-Aufruf heraus, tritt der Effekt nicht mehr auf. Es muß aber auch irgendwie mit dem ?:-Operator zusammenhängen. Der im Grunde äquivalente code

    for (int i = 1; i <= 1000; i++)
    {
        if (i)
        {
            String("1").SubString(1,0);
        }
        else
        {
            String("");
        }
    }
    

    bringt den Effekt nicht hervor.
    Poste doch mal ein Beispiel in eine passende Borland Newsgroup.



  • Hallo dschensky

    ich habe das schon vor geraumer Zeit Borland mitgeteilt, bis heute 0 Antwort. Und das war zu CB5 Zeiten, aber da der CB6 ja den gleichen Effekt zeigt, hat sich seitens Borlands da wohl nix getan.

    Gruß Burkhard



  • Es muss wirklich irgendein Zusammenhang zwischen SubString und dem operator ?:.
    denn, wenn ich

    for (int i = 1; i <= 1000000; i++)
      {
          s = (i==0) ? String("11").SubString(1,1) : String(""); // <= OK
          s = (i==0) ? String("11", 1) : String("");  // <= OK
      }
    

    mache, ist alles ok.
    bei

    for (int i = 1; i <= 1000000; i++)
      {
          s = i ? String("11").SubString(1,1) : String(""); // <= '~*?"!@Beee ;)
          s = i ? String("11", 1) : String("");  // <= OK
      }
    

    wird speicher von 5 mb auf 20 mb. hochgeschaufelt. 😮

    WinXP/BCB 6 Pro



  • Wie schon im Titel angekündigt, scheint der Fehler beim BDS2006 beseitigt worden zu sein, der TestCode von Xqgene verursacht hier keine Speicherlecks mehr.

    Das zur Info. 😉



  • Schon bekannt ...

    ...
    requires a type cast
    from char * to AnsiString, the compiler will allocate a temporary memory
    space to hold the string pointed to by char *, and call the function.
    However, the next time it comes back to the line, another temporary mem
    space is allocated.
    ...


Anmelden zum Antworten