Wie bekomme ich die Speicherblocklänge nach malloc?

Lesezeit: 7 Minuten

Benutzer-Avatar
Amumu

Ich dachte, dass ich die Länge eines zugewiesenen Speicherblocks nicht so einfach abrufen könnte .length Funktion in Java. Allerdings weiß ich jetzt, wann malloc() den Block zuweist, weist es zusätzliche Bytes zu, um eine ganze Zahl zu halten, die die Größe des Blocks enthält. Diese Ganzzahl befindet sich am Anfang des Blocks; die Adresse, die tatsächlich an den Aufrufer zurückgegeben wird, zeigt auf die Stelle direkt hinter diesem Längenwert. Das Problem ist, dass ich nicht auf diese Adresse zugreifen kann, um die Blocklänge abzurufen.

#include <stdlib.h>
#include <stdio.h>
int main(void)
{
        char *str;
        str = (char*) malloc(sizeof(char)*1000);
        int *length;
        length = str-4; /*because on 32 bit system, an int is 4 bytes long*/
        printf("Length of str:%d\n", *length);
        free(str);
}

**Edit: Ich habe es endlich geschafft. Das Problem ist, dass es immer 0 gibt, da die Länge anstelle der Größe auf meinem System darauf zurückzuführen ist, dass mein Ubuntu 64-Bit ist. Ich habe str-4 in str-8 geändert, und es funktioniert jetzt.

Wenn ich die Größe auf 2000 ändere, wird 2017 als Länge ausgegeben. Wenn ich jedoch auf 3000 ändere, gibt es 3009. Ich verwende GCC.

  • Was Sie beschreiben, hängt vollständig von der spezifischen Malloc-Implementierung ab, in der die Informationen auf die von Ihnen beschriebene Weise gespeichert werden. Eine Implementierung von malloc müsste nicht unbedingt verfolgen, wie viel Speicher zugewiesen wurde (unwahrscheinlich, aber möglich, da die API dies nicht tut benötigen diese Informationen werden dem Anrufer angezeigt.)

    – Jo

    27. März 2011 um 18:01 Uhr

  • @Joe: Zum Beispiel könnten Sie ziemlich einfach einen Pool-basierten Allokator implementieren, bei dem beispielsweise alle Zuweisungen der Größe 1-8 aus einem Pool stammen, 9-16 aus einem anderen, 17-32 aus einem anderen usw. Dann statt Da die Größe vor dem nutzbaren Speicher gespeichert wird, könnte jede Zuordnung stattdessen einen Zeiger auf ihren Pool speichern. Große Allokationen müssten jedoch anders behandelt werden.

    – Steve Jessop

    27. März 2011 um 18:44 Uhr


Benutzer-Avatar
Informieren.it

Sie müssen es nicht selbst verfolgen!

size_t malloc_usable_size (void *ptr);

Aber es gibt die tatsächliche Größe des zugewiesenen Speicherblocks zurück! Nicht die Größe, die Sie an malloc übergeben haben!

  • Es ist wichtig zu beachten, dass diese Funktion nicht Teil des C-Standards ist und eine gnulib-Erweiterung ist

    – Degustaf

    24. September 2014 um 14:54 Uhr

  • Nicht nur die Gnulib-Erweiterung

    – CAMOBAP

    1. Januar 2015 um 21:39 Uhr

  • @Hydroper Definitiv nicht. Das erkennt GCC, nicht die GNU C-Bibliothek. Verwenden __GNU_LIBRARY__ stattdessen.

    – SS Anne

    26. September 2019 um 19:36 Uhr

Was du machst ist definitiv falsch. Obwohl es fast sicher ist, dass das Wort direkt vor dem zugewiesenen Block mit der Größe zusammenhängt, enthält es wahrscheinlich einige zusätzliche Flags oder Informationen in den nicht verwendeten Bits. Je nach Implementierung können sich diese Daten sogar in der befinden hoch Bits, was dazu führen würde, dass Sie die völlig falsche Länge lesen würden. Auch ist es möglich, dass kleine Allokationen (zB 1 bis 32 Byte) in spezielle Small-Block-Pages ohne Header gepackt werden, dann ist das Wort vor dem allokierten Block nur Teil eines anderen Blocks und hat in Bezug auf die Größe keinerlei Bedeutung des Blocks, den Sie untersuchen.

Stoppen Sie einfach diese fehlgeleitete und gefährliche Jagd. Wenn Sie die Größe eines erhaltenen Blocks wissen müssen mallocdu machst etwas falsch.

  • Aha. Vielen Dank. Deshalb hat es für jede Größe einen anderen Wert. Ich versuche es nur, um zu sehen, wie es funktioniert, und ich werde das nicht in echten Dingen tun. Es gibt jedoch eine Übung in einem Buch, die erfordert, malloc() und free() basierend auf der erklärten Implementierung zu implementieren, also möchte ich es einfach versuchen.

    – Amumu

    27. März 2011 um 19:22 Uhr

  • Cool, +1 dafür, dass Sie dies als Teil des Experimentierens tun, um “herauszufinden, wie es funktioniert, und zu versuchen, es zu implementieren”, und nicht für eine schreckliche Hackerei.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    27. März 2011 um 19:38 Uhr

  • sizeof(int) ist auf den allermeisten Unix-Systemen immer 4 und wird es wahrscheinlich immer sein. Verwenden long oder noch besser size_t wenn Sie die Systemwortgröße wollen.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    27. März 2011 um 20:11 Uhr

  • @Amumu Nichts ist gefährlich, wenn Sie wissen, was Sie tun, und das Originalplakat nicht fehlgeleitet ist. Es kommt auf die Umsetzung an. Wenn Sie sich die Implementierung im Buch der Programmiersprache C von Brian Kernighan ansehen, gibt es eine allgemeine Version von malloc und free. Ich bin mir nicht sicher, ob es die gleiche Version für GCC ist (höchstwahrscheinlich nicht). Sie können in den Code von GCC schauen und sehen, wo sie die abgelegt haben Header, und schreiben Sie Ihre eigene Funktion zum Abrufen der Header-Informationen. Es wird keine portable Lösung sein, aber wenn Sie es einfach selbst auf demselben Compiler verwenden, wäre es in Ordnung.

    – SwiftMango

    31. Oktober 2012 um 14:26 Uhr


  • @texasbruce: Es ist von Natur aus gefährlich und falsch, es sei denn, Sie programmieren für eine bestimmte Version der spezifischen C-Implementierung (Bibliothek und Compiler), die Sie verwenden werden, und für nichts anderes. Und trotzdem ist diese Annahme gefährlich und falsch, da es wahrscheinlich ist, dass später kritische Fehler in der von Ihnen verwendeten Implementierung gefunden werden und Sie ein Upgrade durchführen müssen, und wenn die von Ihnen getroffenen Annahmen auf der alten Version basieren mit der neuen Version nicht mehr zutrifft, wird Ihr Programm katastrophal abbrechen.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    31. Oktober 2012 um 14:44 Uhr

Benutzer-Avatar
Mike M

Ich würde vorschlagen, dass Sie Ihren eigenen Malloc-Wrapper erstellen, indem Sie eine Datei kompilieren und verknüpfen, die my_malloc() definiert, und dann die Standardeinstellung wie folgt überschreiben:

// my_malloc.c

#define malloc(sz) my_malloc(sz)

typedef struct {
    size_t size;
} Metadata;

void *my_malloc(size_t sz) {
    size_t size_with_header = sz + sizeof(Metadata);
    void* pointer = malloc(size_with_header);

    // cast the header into a Metadata struct
    Metadata* header = (Metadata*)pointer;
    header->size = sz;    
    // return the address starting after the header 
    // since this is what the user needs
    return pointer + sizeof(Metadata);
}

dann können Sie immer die zugewiesene Größe abrufen, indem Sie sizeof(Metadata) subtrahieren, diesen Zeiger auf Metadata umwandeln und metadata->size ausführen:

Metadata* header = (Metadata*)(ptr - sizeof(Metadata));
printf("Size allocated is:%lu", header->size); // don't quote me on the %lu ;-)

  • Dies ist eine gute Problemumgehung, als in den gcc-Quellcode zu schauen.

    – SwiftMango

    31. Oktober 2012 um 14:27 Uhr

  • Beachten Sie, dass der von Ihrem Wrapper zurückgegebene Speicher auf den meisten Architekturen nicht mehr ausgerichtet ist. Ich sollte es wissen, ich habe dasselbe geschrieben und mein Code, der sich auf die Ausrichtung stützt, ist mir in die Luft gesprengt.

    – Thomas

    28. Juni 2013 um 7:53 Uhr


  • Das macht Sinn und dieser Code sollte nur unter strengen Kontrollbedingungen für Debug-Zwecke verwendet werden.

    – Mike M

    26. Juli 2013 um 9:00 Uhr

  • FYI-Zeiger-Arithmetik mit void* ist nicht erlaubt, so dass dieser Code bei kompatiblen Kompilierungen (z. B. GCC mit -pedantic) nicht kompiliert werden kann.

    – Michael Graczyk

    3. Juni 2014 um 6:40 Uhr

  • @Thomas Um die Ausrichtung zu korrigieren, könnten Sie eine Vereinigung mit einem Mitglied vom Typ max_align_t verwenden: typedef union { size_t size; max_align_t ma; } Metadaten;

    – Fernando Costa Bertoldi

    16. Juni 2016 um 22:40 Uhr


Das darfst du nicht. Wenn Sie wissen möchten, wie viel Speicher Sie zugewiesen haben, müssen Sie selbst den Überblick behalten.

Wenn Sie außerhalb des Ihnen zurückgegebenen Speicherblocks suchen (vor dem von malloc zurückgegebenen Zeiger oder nach diesem Zeiger + der Anzahl der angeforderten Bytes), führt dies zu einem undefinierten Verhalten. Es könnte in der Praxis für eine bestimmte Malloc-Implementierung funktionieren, aber es ist keine gute Idee, sich darauf zu verlassen.

Dies ist nicht Standard C. Es soll jedoch auf Windows-Betriebssystemen funktionieren und möglicherweise auch auf anderen Betriebssystemen wie Linux (msize?) oder Mac (alloc_size?) verfügbar sein.

size_t _msize(void *memblock);

_msize() gibt die Größe eines im Heap allokierten Speicherblocks zurück.

Siehe diesen Link:
http://msdn.microsoft.com/en-us/library/z2s077bc.aspx

Benutzer-Avatar
Schwarzbär

Dies ist implementierungsabhängig

Benutzer-Avatar
Oleiade

Jedem Block, den Sie zuweisen, geht ein Blockdeskriptor voraus. Das Problem ist, es hängt von der Systemarchitektur ab. Versuchen Sie, die Blockdeskriptorgröße für Ihr eigenes System zu finden. Versuchen Sie, einen Blick auf Ihre System-Malloc-Manpage zu werfen.

  • Nicht unbedingt. Siehe meine Antwort.

    – R.. GitHub HÖR AUF, EIS ZU HELFEN

    27. März 2011 um 19:01 Uhr

1144630cookie-checkWie bekomme ich die Speicherblocklänge nach malloc?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy