Wie gibt man eine verkettete Struktur nach malloc frei ?



  • Hallo, ich verwende gerade die IPHelper API, und hole mir die Netwerk MAC Adresse daraus.
    Nun habe ich eine Frage zu den komischen Strukturen:

    PIP_ADAPTER_INFO pAdInfo = NULL;
    	GetAdaptersInfo(pAdInfo, &buflen);
    

    Ich bekomme "einen" Pointer auf eine PIP_ADAPTER_INFO Struktur aber am Anfang dieser Struktur einen weiteren Pointer auf eine weitere PIP_ADAPTER_INFO Struktur des nächsten Netzwerkadapters.
    In der MSDN wird der erste Pointer gespeichert und am Schluss mit Free() freigegeben, aber das kann doch nicht sein.
    Ich denke doch mal die Größe des ersten Pointers ist sizeof(PIP_ADAPTER_INFO), hat ja auch die Deklariation wie oben.
    Müsste man hier nicht nach jedem ->Next Pointer den vorliegenden Pointer mit free() behandeln ?

    typedef struct _IP_ADAPTER_INFO {
      struct _IP_ADAPTER_INFO {
      }* Next;
      DWORD ComboIndex;
      char AdapterName[MAX_ADAPTER_NAME_LENGTH + 4];
      char Description[MAX_ADAPTER_DESCRIPTION_LENGTH + 4];
      UINT AddressLength;
      BYTE Address[MAX_ADAPTER_ADDRESS_LENGTH];
      DWORD Index;
      UINT Type;
      UINT DhcpEnabled;
      PIP_ADDR_STRING CurrentIpAddress;
      IP_ADDR_STRING IpAddressList;
      IP_ADDR_STRING GatewayList;
      IP_ADDR_STRING DhcpServer;
      BOOL HaveWins;
      IP_ADDR_STRING PrimaryWinsServer;
      IP_ADDR_STRING SecondaryWinsServer;
      time_t LeaseObtained;
      time_t LeaseExpires;
    } IP_ADAPTER_INFO, 
     *PIP_ADAPTER_INFO;
    

    http://msdn.microsoft.com/en-us/library/aa365917(VS.85).aspx

    Grüße
    Thenoname



  • Warum? Hier wird nur eine verkettete Liste aufgebaut. Wenn es keinen weiteren Adapter gibt, ist der Next-Pointer NULL. Das Free kommt nur, wenn die nächste Adapterstruktur auch vorhanden ist:

    if (pAdapterInfo)
            FREE(pAdapterInfo);
    
        return 0;
    


  • Wird denn die malloc Größe zum Freigeben verwendet oder die Größe/Länge "einer" Struktur ?

    ps. so wie du oben schreibst, hätte ich es gemacht, aber die MSDN nimmt den "Ersten" Pointer und befreit nicht jede Struktur die != NULL ist.



  • thenoname schrieb:

    Wird denn die malloc Größe zum Freigeben verwendet oder die Größe/Länge "einer" Struktur ?

    malloc/free wissen nichts von Strukturen.

    thenoname schrieb:

    ps. so wie du oben schreibst, hätte ich es gemacht, aber die MSDN nimmt den "Ersten" Pointer und befreit nicht jede Struktur die != NULL ist.

    Das Beispiel in der MSDN Library holt zunächst einen Puffer in der Größe einer Struktur, um die tatsächlich benötigte Größe zu ermitteln. Danach wird dieser Puffer freigegeben, und ein neuer in der passenden Größe geholt (das 2. malloc).

    Der zweite Puffer wird allerdings nicht wieder freigegeben (Speicherleck).



  • nönönö,

    pAdapter = pAdapterInfo;

    der pAdapter geht durch alle Verkettungen, der pAdapterInfo wird am Schluss mit:

    if (pAdapterInfo)
            FREE(pAdapterInfo);
    

    freigegeben.
    Er wird nicht einmal annähernd dieser Pointer pAdapterInfo angefasst.
    pAdapterInfo hat zudem nicht die Größe "einer" Struktur sondern die Buffergröße. (laut dem malloc)

    ps. erstes malloc ist klar zum Größe ermitteln !



  • thenoname schrieb:

    nönönö,

    pAdapter = pAdapterInfo;

    der pAdapter geht durch alle Verkettungen, der pAdapterInfo wird am Schluss mit:

    if (pAdapterInfo)
            FREE(pAdapterInfo);
    

    freigegeben.

    Ok, ich hatte in meine lokale MSDN geschaut. Das aktuelle Beispiel im Web sieht so aus, wie du es beschreibst.

    thenoname schrieb:

    Er wird nicht einmal annähernd dieser Pointer pAdapterInfo angefasst.

    Muss ja auch nicht. Der Zeiger wird nur noch zum Freigeben gebraucht.

    thenoname schrieb:

    pAdapterInfo hat zudem nicht die Größe "einer" Struktur sondern die Buffergröße.

    Das ist ja auch der Sinn der Sache. GetAdaptersInfo schreibt die gesamte Liste in einen einzigen Puffer. Nur den musst du freigeben, denn nur den hast du alloziiert.



  • Jo, danke, jetzt issses klar.

    Was macht delete mypointer ?
    Wird hier nur der pointer = 4 Byte freigegeben ?
    Das muss ich doch nie tun = geht automatisch ?

    Grüße
    thenoname



  • thenoname schrieb:

    Was macht delete mypointer ?

    Wenn mypointer auf etwas zeigt, das mit new alloziiert wurde, wird das, worauf der Zeiger zeigt, wieder freigegeben.

    thenoname schrieb:

    Wird hier nur der pointer = 4 Byte freigegeben ?

    Nein. delete ändert den Zeiger selbst überhaupt nicht.

    thenoname schrieb:

    Das muss ich doch nie tun = geht automatisch ?

    Das, was delete tut, passiert niemals automatisch.



  • Ach und noch eine Frage 😉

    wenn ich einen Pointer mit malloc behandle habe ich ihn bei free() zum löschen
    mit der mit malloc definierten Größe.
    Was ist nun aber, wenn ich mittendrinn

    mystorepointer=mypointer;
    

    benutze ? Werden die malloc Infos=Größe mittransferiert auf mystorepointer und ich
    kann hier einen free() ausführen oder hat die Größe nur mypointer ?

    Grüße



  • thenoname schrieb:

    Was ist nun aber, wenn ich mittendrinn

    mystorepointer=mypointer;

    benutze ?

    Welcher von den beiden zeigte auf mit malloc geholten Speicher?
    Wenn es mystorepointer war, hast du ein Speicherleck. Wenn es mypointer war, könntest du hinterher free mit jedem der beiden Zeiger aufrufem (aber nur mit einem).



  • Sorry, ich malloc(e) vorher mypointer 😉

    Danke für die Antworten, jetzt habe ich es endlich mal kappiert !

    Kann man "new" und malloc mischen ?

    Also mit malloc Speicher holen und mit delete wieder freigeben ?



  • thenoname schrieb:

    Kann man "new" und malloc mischen ?

    Also mit malloc Speicher holen und mit delete wieder freigeben ?

    Generell Nein. Es gibt bestimmte Situationen mit manchen Compilern, in denen das möglicherweise funktioniert. Lass dich aber auf so etwas nicht ein, weil das nicht vom Standard abgedeckt ist, und möglicherweise irgendwann nicht mehr funktioniert.


  • Mod

    thenoname schrieb:

    wenn ich einen Pointer mit malloc behandle habe ich ihn bei free() zum löschen
    mit der mit malloc definierten Größe.
    Was ist nun aber, wenn ich mittendrinn

    mystorepointer=mypointer;
    

    benutze ? Werden die malloc Infos=Größe mittransferiert auf mystorepointer und ich
    kann hier einen free() ausführen oder hat die Größe nur mypointer ?

    Das spielt gar keine Rolle! Der Zeiger selbst verweist auf den Speicher und ist in einem 32bit System 4Byte groß.
    Wichtig ist, dass Du den Sepciher eben genau einmal freigibst. Wie die Vraiable heißt spielt keine Rolle.

    Technisch gesehen, wird einfach im Bereich Pointer-x ein Block mitgeführt in dem die Daten stehen. Wie das genau geht kannst Du einfach im CRT Sourcecode nachlesen, besonderrs interessant ist hier der Debug Code, der zusätzliche Plausis bietet.



  • wird einfach im Bereich Pointer-x ein Block mitgeführt in dem die Daten stehen

    Das war mir bis jetzt eben nicht bekannt. Es werden also Informationen von malloc dort in diesen Block hineingeschrieben. Bis jetzt war ein Pointer für mich eben nur ein Zeiger = 4 Byte, der auf einen Speicherbereichanfang zeigt. Von Größeninformationen wie bei einem vector habe ich noch nichts gewusst.
    Man muss dann aber immer davon ausgehen, das z.B. ein char* mypointer mit 4 Charactern erzeugt mit malloc nicht 4 Byte gross ist sondern 4Byte + Informationen.

    Free() muss dann diesen Block selbsständig finden.


  • Mod

    thenoname schrieb:

    Das war mir bis jetzt eben nicht bekannt. Es werden also Informationen von malloc dort in diesen Block hineingeschrieben.

    Was dachtest Du wie der Heap organisiert wird. Er ist selbst eine Art verkette Struktur oder Baum. Zusätzlich werden oft genug Guard Bytesmit allokiert, die helfen bei der Analyse wenn Speicher über die Grenzen hinaus überschrieben wird.

    thenoname schrieb:

    Bis jetzt war ein Pointer für mich eben nur ein Zeiger = 4 Byte, der auf einen Speicherbereichanfang zeigt.

    Nein! Es ist weitaus mehr. Wenn Du 4 Bytes allokierst gibt es IMHO 16 Bytes Overhead. Deshalb gibt ist auch eine Begrenzung nach unten. IMHO werden minimal 32 Bytes Speicher allokiert´. Aber das hängt vom Speicher Manager ab.

    thenoname schrieb:

    Von Größeninformationen wie bei einem vector habe ich noch nichts gewusst.
    Man muss dann aber immer davon ausgehen, das z.B. ein char* mypointer mit 4 Charactern erzeugt mit malloc nicht 4 Byte gross ist sondern 4Byte + Informationen.

    Jupp!

    thenoname schrieb:

    Free() muss dann diesen Block selbsständig finden.

    Nein! Du übergibst die Speicheradressse, die Du erhalten hast, -x Bytes beginnen bei einem korrekt allozierten Block eben die malloc/new Infos.


Anmelden zum Antworten