web-dev-qa-db-ja.com

malloc後のメモリブロック長を取得する方法は?

Javaの単純な_.length_関数のように、割り当てられたメモリブロックの長さを取得できないと思いました。ただし、malloc()がブロックを割り当てると、ブロックのサイズを含む整数を保持するために追加のバイトが割り当てられることがわかりました。この整数はブロックの先頭にあります。発信者に実際に返されるアドレスは、この長さの値を少し超えた場所を指します。問題は、そのアドレスにアクセスしてブロック長を取得できないことです。

_#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);
}
_

**編集:私はついにそれをしました。問題は、Ubuntuが64ビットであるため、システムのサイズではなく長さとして0が表示され続けることです。 str-4をstr-8に変更しましたが、動作するようになりました。

サイズを2000に変更すると、長さとして2017が生成されます。ただし、3000に変更すると、3009になります。GCCを使用しています。

16
Amumu

あなたがしていることは間違いなく間違っています。割り当てられたブロックの直前のWordがサイズに関連していることはほぼ確実ですが、それでも、未使用のビットにいくつかの追加のフラグまたは情報が含まれている可能性があります。実装によっては、このデータがhighビットである場合もあり、完全に間違った長さを読み取る可能性があります。また、小さな割り当て(1〜32バイトなど)がヘッダーのない特別な小さなブロックページにパックされる可能性もあります。その場合、割り当てられたブロックの前のWordは別のブロックの一部であり、サイズに関しては何の意味もありません。あなたが調べているブロックの。

この見当違いで危険な追跡をやめてください。 mallocによって取得されたブロックのサイズを知る必要がある場合は、何か問題があります。

自分で追跡する必要はありません!

size_t malloc_usable_size(void * ptr);

ただし、割り当てられたメモリブロックの実際のサイズが返されます。 mallocに渡したサイズではありません!

25
Informate.it

My_malloc()を定義するファイルをコンパイルしてリンクし、次のようにデフォルトを上書きして、独自のmallocラッパーを作成することをお勧めします。

// 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);
}

次に、sizeof(Metadata)を減算し、そのポインターをメタデータにキャストし、metadata-> sizeを実行することで、割り当てられたサイズをいつでも取得できます。

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

これは標準Cではありません。ただし、Windowsオペレーティングシステムで動作するはずであり、Linux(msize?)やMac(alloc_size?)などの他のオペレーティングシステムでも使用できる可能性があります。

size_t _msize(void * memblock);

_msize()は、ヒープに割り当てられたメモリブロックのサイズを返します。

このリンクを参照してください: http://msdn.Microsoft.com/en-us/library/z2s077bc.aspx

7
Indinfer

あなたはそれをすることになっていない。割り当てたメモリの量を知りたい場合は、自分でそれを追跡する必要があります。

返されたメモリブロックの外側を見ると(mallocから返されるポインタの前、またはそのポインタ+要求したバイト数の後)、未定義の動作が発生します。特定のmalloc実装で実際に機能する可能性がありますが、それに依存することはお勧めできません。

6
metamatt

これは実装に依存します

4
BlackBear

私の(Ubuntu)システムでこのアプリを実行すると、次のようになります。

Length of str:1009
1
karlphillip

割り当てるすべてのブロックの前には、ブロック記述子があります。問題は、システムアーキテクチャに依存することです。自分のシステムのブロック記述子サイズを見つけてください。システムmallocのmanページを見てみてください。

0
Oleiade