2009-08-20 6 views
5

Nehmen wir an, ich habe einen Zeiger zugewiesen, um 4096 Bytes zu halten. Wie würde man die letzten 1024 Bytes in C freigeben? Was ist mit C++? Was, wenn ich stattdessen die erste 1024 Bytes freigeben wollte, und den Rest behalten (in beiden Sprachen)? Wie wäre es mit der Freigabe aus der Mitte (es scheint mir, dass dies die Aufteilung in zwei Zeiger vor und nach der freigegebenen Region erfordern würde).C und C++: Freigeben von Teil eines zugewiesenen Zeigers

+0

nicht sicher darüber, aber mit "falschen" Zeiger mit der richtigen Größe, Löschen oder Befreien der eine, die Sie wollen, sollten den Trick tun, brauchen mindestens 2 Zeiger. – claf

+1

@claferri. Das ist undefiniertes Verhalten. Sie können nur() Zeiger freigeben, die von malloc/realloc zurückgegeben werden - ansonsten, wie kann free() wissen, wie viel zu befreien ist? – Roddy

+0

@roddy: oups du hast Recht :) – claf

Antwort

2

Wenn Sie n Bytes malloc ated Speicher haben, können Sie reallocm Bytes (wo m < n) und damit die letzten n-m Bytes wegzuwerfen.

Um von Anfang weg zu werfen, können Sie malloc einen neuen, kleineren Puffer und memcpy die Bytes, die Sie wollen, und dann free das Original. Die letzte Option ist auch verfügbar unter Verwendung von C++ new und delete. Es kann auch den ersten realloc Fall emulieren.

+1

"malloc/memcpy/free" ist wie Realloc intern implementiert werden kann. – Roddy

+1

Ich stimme zu, dass Realloc in der Regel den (gleichen) ersten Teil zurückgibt, aber ist es eine offizielle Voraussetzung für Realloc? Ich denke, hier könnten Implementierungen die Daten an einen neuen Ort verschieben. –

+0

Stellen Sie sich ein intelligentes Neuzuteilungsschema vor, bei dem das historische Zuteilungsmuster verfolgt wird ... wenn kürzlich Zuteilungsanforderungen für 4096 Byte aufgetreten wären, könnte es besser sein, den schrumpfenden Block anderswo zu verschieben, um diesen 4K-Block freizugeben. In diesem Fall ändert sich die Adresse. Und Realloc gibt einen Zeiger auf den neuen Speicherbereich zurück, so dass der Programmierer es verwenden sollte. Ob es sich ändert oder nicht. – xcramps

1

Sie können es mit realloc() kürzer machen. Ich glaube nicht, dass der Rest möglich ist.

1

Sie können realloc() verwenden, um den Speicher scheinbar kürzer zu machen. Beachten Sie, dass bei einigen Implementierungen ein solcher Aufruf tatsächlich nichts bewirkt. Sie können das erste Bit des Blocks nicht freigeben und das letzte Bit beibehalten.

Wenn Sie diese Art von Funktionalität benötigen, sollten Sie eine komplexere Datenstruktur in Betracht ziehen. Ein Array ist nicht die richtige Antwort auf jedes Programmierproblem.

+0

Ich implementiere ein Speichersystem, also suche ich nach Low-Level-Zugriff wie ich kann, während immer noch tragbar. – Imagist

1

http://en.wikipedia.org/wiki/New_(C%2B%2B)

ZUSAMMENFASSUNG: Im Gegensatz zu C des realloc, es nicht möglich ist, direkt Speicher mit new [] zugewiesen neu zuzuteilen. Um zu erweitern oder die Größe eines Blocks zu reduzieren, muss ein einen neuen Block von adäquater Größe zuweisen, über den alten Speicher kopieren und den alten Block löschen. Die C++ - Standardbibliothek bietet ein dynamisches Array, das in seiner Std :: Vector-Vorlage erweitert oder reduziert werden kann.

12

Versuchen Sie nicht, Speicherverwaltung zu zweit zu erraten. Es ist in der Regel schlauer als Sie

Das einzige, was ;-) Sie ist das erste Szenario ‚ausplanen‘ erreichen letzten 1K

char * foo = malloc(4096); 

foo = realloc(foo, 4096-1024); 

Doch selbst in diesem Fall gibt es keine Garantie, dass „foo "wird unverändert bleiben. Ihre gesamte 4K-Datei kann freigegeben werden, und realloc() kann Ihren Speicher an anderer Stelle verschieben, wodurch alle darauf enthaltenen Zeiger ungültig werden.

Dies ist gültig für C und C++ - jedoch ist die Verwendung von malloc() in C++ ein schlechter Code Geruch, und die meisten Leute würden erwarten, dass Sie new() Speicherplatz zuweisen. Und Speicher, der mit new() zugewiesen wurde, kann nicht neu zugeordnet werden - oder zumindest nicht in irgendeiner Art und Weise.STL-Vektoren wäre ein viel besser Ansatz in C++

5

Sie haben nicht "einen Zeiger für 4096 Bytes reserviert", Sie haben einen Zeiger auf einen zugewiesenen Block von 4096 Bytes.

Wenn Ihr Block mit malloc() belegt wurde, können Sie mit realloc() die Größe des Blocks reduzieren oder vergrößern. Die Startadresse des Blocks bleibt jedoch nicht unbedingt gleich.

Sie können die Startadresse eines malloc Speicherblocks nicht ändern, was Ihr zweites Szenario wirklich ist. Es gibt auch keine Möglichkeit, einen malloc Block zu teilen.

Dies ist eine Einschränkung der malloc/calloc/realloc/free API - und Implementierungen können auf diesen Einschränkungen (zum Beispiel verlassen, Buchhaltung Informationen über die Zuteilung unmittelbar vor der Startadresse zu halten, die die Startadresse machen würden bewegen Jetzt schwer)

, malloc ist nicht die einzige allocator da draußen -. Ihre Plattform oder Bibliotheken könnten andere, die zur Verfügung stellen, oder Sie können Ihre eigenen schreiben (die Speicher aus dem System über malloc bekommt, mmap, VirtualAlloc oder einige anderen Mechanismus) und übergibt es dann Ihrem Programm in der von Ihnen gewünschten Weise.

Für C++, wenn Sie Speicher mit std::malloc zuweisen, gelten die obigen Informationen. Wenn Sie new und delete verwenden, ordnen Sie Speicher für Objekte zu und konstruieren Objekte. Daher ist es nicht sinnvoll, die Größe eines zugewiesenen Blocks zu ändern - Objekte in C++ haben eine feste Größe.

Verwandte Themen