p = root; // durchlaufe die gesamte Liste von Blöcken bis zum Ende while ( NULL != p ) {
// ist dieser Block unbenutzt und groĂź genug if ( ( 0 == p->used ) && ( s < p->size + sizeof( HeapHdr_t ) ) ) {
// ein neuer Block für den übrigen freien Speicher wird // generiert und hinter dem zu verwendenden in die Liste // eingefügt np = (HeapHdr_t *) ((unsigned char *)p + sizeof( HeapHdr_t ) + s); // der Nachfolger bleibt identisch np->next = p->next; // der Nachfolger des Blockes p muss nun auf den neuen // Block np verweisen, falls es einen Nachfolger gibt if ( NULL != p->next ) p->next->prev = np; // Der Vorgänger von np ist p np->prev = p; // der neue Block hat die Groesse des noch freien // Speichers und ist nicht benutzt np->size = p->size - s - sizeof( HeapHdr_t ); np->used = 0;
// nachdem der neue Block fĂĽr den ĂĽbrigen Speicher // angelegt wurde, kann der alte Block verwendet werden p->size = s; p->used = 1; p->next = np;
// der Pointer zum Nutzdatenbereich wird dem User // zurĂĽckgegeben return (void*) ((unsigned char*)p + sizeof( HeapHdr_t ) ); }
// nächsten Block betrachten p = p->next;
} // while
// wurde beim Durchlauf kein nutzbarer Block gefunden, gibt // die Funktion NULL zurĂĽck return NULL; }
// der vom Benutzer übergebene Zeiger ist eigentlich ein Zeiger // auf hdr->usermem. Man erhält den richtigen Zeiger für hdr, indem // den Benutzerzeiger um die Größe des Headers nach vorn // verschoben wird hdr = (HeapHdr_t *) ( (unsigned char *)userp - sizeof( HeapHdr_t ) );
// mit dem folgenden Schritt ist der Speicherbereich schon wieder // freigegeben und könnte verwendet werden hdr->used = 0;
// Testen, ob der darauffolgende Block auch frei ist if ( 0 == hdr->next->used ) { // neue Größe dieses Blockes aus der Summe beider hdr->size += hdr->next->size + sizeof( HeapHdr_t );
// Nun muss der nachfolgende Block aus der doppelt verketteten // Liste entfernt werden. Dazu wird zuerst der prev Zeiger des // Nachfolgers des nächsten Blockes auf diesen Block verbogen: if ( NULL != hdr->next->next ) hdr->next->next->prev = hdr->next->prev; // Nun wird der aktuelle Nachfolger auf den Nachfolger des // nächsten Blockes umgelegt: hdr->next = hdr->next->next; // Damit ist der Block hdr->next aus der doppelt verketteten // Liste entfernt worden } }