Aufgabe 3 - halde

Disclaimer: Dieser Thread wurde aus dem alten Forum importiert. Daher werden eventuell nicht alle Formatierungen richtig angezeigt. Der ursprüngliche Thread beginnt im zweiten Post dieses Threads.

Aufgabe 3 - halde
Hallo zusammen!

Ich hätte eine Frage zur halde-Aufgabe:
Der zu verwaltende Speicher ist 102410241 Byte, also 1MiB groß.
Ich war schon in der Übung zu der Aufgabe. Aber was mir jetzt immer noch nicht so ganz klar ist, ist folgendes:
Der Platz, den man für ein Listenelement braucht, ist auf einem 64-Bit-Rechner 28=16 Byte.
In der Aufgabenstellung (unvollständige Checklist) steht:
“Die Anforderung eines Speicherbereiches der Größe (1 MiB - Größe eines Listenelementes) ist erfolgreich.”.
Aber der maximale Speicherbereich, der angefordert werden kann ist doch 1MiB-sizeof(mblock), oder nicht?
Bzw 1MiB-2
sizeof(mblock), wenn man nach dem reservierten Speicherbereich noch eine Verwaltungsstruktur (mit freiem Speicher 0) einfügt.

Kann mir dazu jemand eine Hilfestellung/Antwort geben?

Vielen Dank!


Ja, der ist genau 1MiB-sizeof(mblock).

Eine Verwaltungsstruktur, die 0 Byte verwaltet sollte nicht angelegt werden, da dadurch einfach nur Speicher verschwendet wird.

Was genau möchtest du wissen?


Sorry, mir fällt auch gerade auf, dass mir der wirkliche Punkt der Aussage gefehlt hat :smiley:

Aber ich wollte genau das wissen, was Du mir gerade beantwortet hast.
Nämlich, dass die maximale Größe, die angefordert werden kann 1MiB-sizeof(mblock) ist.

Danke!


liege ich damit richtig als zeiger auf den neu allocierten speicher einen zeiger auf das memory des verwaltenden listenelements zurück zu geben?
damit hauts mir das ganze nämlich beim free um die ohren…


Damit liegst du richtig - vorausgesetzt, du schmeißt dieses Element dann auch bei der Allokation aus der Freispeicherliste raus. Der Fehler liegt dann vermutlich eher an anderer Stelle.


Soll denn die errno gesetzt werden, falls unsere Implementierung von malloc auf einen Fehler stößt, also z.B. nicht mehr genug Speicher vorhanden ist oder so etwas?


Klar! So wie das echte [m]malloc()[/m] halt auch - siehe Man-Page.


Ah okay, vielen Dank!

Aber bei mir kommt jetzt eine ganz andere Frage auf:
Wir haben ja das statische char-Array memory gegeben:

static char memory[SIZE];

Auf den Folien steht folgendes:

//struct mblock reinlegen
mblock* head = (struct mblock*) memory;

Das ist beim ersten Element ja auch kein Problem.
Wenn man jetzt das erste Verwaltungselement angelegt hat, dann muss man (falls noch Platz ist) das nächste Listenelement bereits anlegen und auch in den durch das memory-Array reservierten Speicher legen.
Doch ich habe keine Ahnung, wie ich in C jetzt angeben kann, an welcher Stelle des reservierten Speichers dieses neue Element abgelegt werden soll.
Kann mir da jemand helfen?

Mit new = (mblock*)memory[4711]; oder new = (mblock*)memory+4711; geht nichts. Auch meine Google-Suche verlief weitestgehend erfolglos.


Warum geht es so nicht?

Du musst schon mit Zeigerarthmetik die Speicherstelle für die neue Verwaltungsstruktur bestimmen. Allerdings darfst du nicht bei memory beginnen, sondern musst vom aktuellen Listenelement ausgehen.


Das heißt aber auch, wenn ich z.B. head++ mache, dass er dann halt sizeof(mblock*)+sizeof(size_t) Byte weitergehen würde, oder?
Folglich müsste ich das aktuelle Element erst einmal zu (char*) casten, sodass ich genau die Anzahl an Byte bestimmen kann, die ich weitergehen will.
Ist das so halbwegs richtig bzw. nachvollziehbar?

EDIT: Es klappt jetzt soweit und stimmt auch mit den Tests der Vorgabe überein. Nur in einem Fall bin ich verblüfft.
Wenn ich malloc(SIZE) also malloc(102410241) mache, dann legt die Vorgabe etwas an, bei malloc(102410241-sizeof(mblock)) jedoch nicht.
Das ist mir nicht ganz ersichtlich, da ja vorher gesagt wurde, dass die maximale Speichergröße, die gefordert werden kann 1MiB-sizeof(mblock) ist.


Es ist nachvollziehbar und casten ist hier eine Lösung. Allerdings bietet dir die [m]struct mblock[/m] bereits einen [m]char*[/m] an eine definiert Stelle an.

Die Ausgabe von printList zeigt nur den internen Zustand der Freispeicherliste an.
Im Falle von [m]malloc(102410241)[/m] wird der Speicherbereich initialisiert und anschließend wird festgestellt, dass kein Element in der Freispeicherliste vorhanden ist, das genug Platz bietet. Also sollte [m]NULL[/m] zurückgegeben werden.
Im Falle von [m]malloc(102410241-sizeof(mblock))[/m] wird ebenfalls der Speicherbereich initialisiert und das einzige Element der Freispeicherliste als belegt markiert, da es die Anforderung erfüllen kann. Natürlich wird auch ein Zeiger ungleich NULL von malloc zurückgeliefert.


Verstehe ich das richtig wenn ich daraus folgere, dass der letzte (und in diesem Fall einzige) Speicherbereich keinen mblock nach sich braucht, sondern einfach mit dem insgesamt verfuegbaren Speicherbereich endet? Sonst muesste ja die maximal anlegbare Groesse (102410241-2*sizeof(mblock))-1 sein.


Das trifft nicht nur auf den letzten Speicherbereich zu, sondern auf die Situationen, wo kein zusaetzlicher mblock mehr reinpasst… Muss man sich Gedanken machen, wie der allgemeine Fall dafuer ausschaut, die Situation kann (und wird in den Testcases :smiley: ) ja auch in der „Mitte“ der Liste auftreten.


Wie soll malloc sich dann aber verhalten wenn ich beispielsweise ganz am Anfang ein malloc mit (1024*1024 - sizeof(mblock) - 1) mache? Entweder das eine Byte wird nicht verwaltet oder ich gebe NULL zurueck, da ich keine unverwalteten Bytes haben will und ein weiterer mblock nicht reinpasst.


Wenn du dieses Byte auch nur einmal aus der Verwaltung rausnimmst, wirst du es nie wieder verwalten können…

Die Lösung: Rück einfach den kompletten Block raus. Der ist dann minimal größer als angefordert (= interner Verschnitt), aber dafür geht kein Speicher unwiederbringlich verloren.


Hallo zusammen,

wahrscheinlich ist es eine bloede Frage, aber ich habe zwei kleine Probleme mit der
Halden-Aufgabe:

  1. Makefile:
    immer wenn ich versuche meine test.o und halde-ref.o zu test-ref zu wandeln, bekomme
    ich folgende Fehlermeldung:
    i386:x86-x64 architecture of input file ‘halde-ref.o’ is incompatible with i386 output
    Was mache ich falsch?

2.halde.c
wenn ich halde.c mit gcc kompiliere, dann gibt er mir zwei Fehlermeldungn fuer die printList-Methode, die
ja vorgegeben war. Und zwar meckert er bei Zeile 32 und 34, dass %lx bzw. &lu ein Argument des Types
long unsigned int erwarten wuerde, das Argument jedoch nur ein unsigned-int ist. Soll ich da jetzt tatsaechlich die printList-Methode veraendern oder kompiliere ich mit den falschen Flags bzw. mache sonst etwas falsch?

Vielen Dank im Vorraus schon mal fuer die hoffentliche Aufklaerung.


Ist das auf deiner privaten Kiste daheim?

Die Vorgabe geht davon aus, dass du deinen Code auf einem x86_64-System (bevorzugt direkt im CIP) baust und ausführst, und ist nicht mit 32-Bit-Systemen kompatibel.


Die Sunray-Server haben noch ein 32-Bit-Userland. Da wird es auch nicht funktionieren. Also an anderen Rechner setzen oder SSH.

1 Like

Hallo. Ich steh grad aufm Schlauch. Ich habe bereits alle Funktionen ausprogrammiert.
Das einzige was noch fehlt ist den head Pointer zu initialisieren. Bei der Deklaration kann ich
ihn auf den memory Pointer setzen, das ist mir schon klar. Aber wo kann ich die head->Size
mit SIZE - sizeof(mblock) initialisieren. Bei C gibts keinen Konstruktor :blush: