2

大規模なアプリケーションによって現在割り当てられているメモリの量を追跡したいと考えています。

メモリ割り当て呼び出しをインターセプトするために、malloc/free/realloc にフックをインストールできることがわかりました。

http://man7.org/linux/man-pages/man3/malloc_hook.3.html

したがって、追跡したいのは、割り当てられた合計バイト数と解放された合計バイト数です。

ここでの問題は、 free がサイズではなくポインターのみを取ることです。

では、malloc フックで独自のマップまたはハッシュマップを作成できます。これは、そのポインターに割り当てられたメモリの量を追跡しますが、かなりのオーバーヘッドが発生します。

free が呼び出されたときに (デフォルトの g++ malloc で) Linux (64 ビット) で ptr のサイズを取得する方法はありますか?

4

4 に答える 4

5

linux man malloc_usable_size

malloc_usable_size() は、動的に割り当てられたバッファー ptr で使用可能なバイト数を返します。これは、要求されたサイズよりも大きい場合があります (ただし、要求が成功した場合は、少なくとも同じ大きさであることが保証されます)。通常、この関数を使用するのではなく、要求された割り当てサイズを格納する必要があります。

于 2013-03-12T17:37:40.017 に答える
2

これはあなたの質問に対する直接的な答えではありませんが、割り当てられたメモリの合計に興味があるので、解決策は次のとおりです。

uordblksそれが返す構造体のフィールドに最も興味があると思います。

これは標準の POSIX 関数ではないことに注意してください。

于 2013-03-12T17:38:50.530 に答える
1

メモリブロックのサイズは通常、ポインタのすぐ下に格納されます。これはハックですが(あなたは私ができると言っていました...)、次のコードが私のLinuxボックスで実行されます:

#include <stdio.h>
#include <stdlib.h>

int main(){
int *p, n=123;
p = (int*)malloc(n*sizeof(int));
printf("allocated %d bytes for p\n", n*sizeof(int));
printf("p[-2] : %d \n", *(p-2));
printf("malloc_useable_size(p) : %d\n", malloc_usable_size(p));
free(p);
}

生成される出力は次のとおりです。

allocated 492 bytes to p
p[-2] : 513
malloc_useable_size(p): 504

p [-2]のサイズは正確ではないことに注意してください492。ハウスキーピングや境界の調整などにより、追加のスペースが消費されます。

また、注意してください-これはgccコンパイラで機能しました。しかしg++、ポインタ変換について不平を言い、私は宣言していませんでしたmalloc_useable_size()。@fanlの答えを見た後、好奇心からその行を追加しました。mallinfo@OliCharlesworthの回答を見た後の出力も少し遊んでみました。

nの値を変更すると、状況が非常によく一致することがわかります。たとえば、n(上記のコードで)を100から119にステップすると、対象となるさまざまな変数の値は次のようになります。

  n | p[-2] | usable | uordblks
----+-------+--------+---------
100    417     408       416
101    417     408       416
102    417     408       416
103    433     424       432
104    433     424       432
105    433     424       432
106    433     424       432
107    449     440       448
108    449     440       448
109    449     440       448 
110    449     440       448
111    465     456       464   
112    465     456       464
113    465     456       464
114    465     456       464
115    481     472       480
116    481     472       480
117    481     472       480
118    481     472       480
119    497     488       496 

usableとの間、およびp[-2]との1間には常に9の違いがp[-2]ありuordblksます。このメソッドの利点は、要求した内容、つまりこのポインターのサイズがp[-2]正確にわかることです。他の呼び出しは実際にあなたが本当に欲しかったものをあなたに伝えるかもしれません...

PS非常に大きなメモリブロックの場合、にあるを調べる必要がある可能性がありlong integerます*((long int*)(p)-1)。それは私に素晴らしいマクロのインスピレーションを与えてくれます:

#define PSIZE(a) (*((long int*)(a)-1))

次に、ポインタのサイズを次のように確認できます。

printf("my pointer size is %ld\n", PSIZE(myPointer));

ポインタの種類を気にする必要はありません。これがさまざまなタイプのポインター、および4Gを超えるブロックで機能することを確認しました。明らかに、数値がmallinfo()と正確に一致するように、マクロで1を引くことを決定できます。

編集:ポインタのすぐ下に何が格納されているかについてのより完全な説明は、この以前の質問に対する回答の1つに記載されています。これは、私が観察した「+1」が実際にはLSBに格納されているフラグによるものであることを示しています。正しいアプローチは、結果を〜3でANDし、2つのLSBをクリアしてから、結果から(long int *)のサイズを減算することです(実際には、元の回答は2 * sizeof(unsigned long int)を減算しますが、それは間違い):

#define PSIZE(a) ((*((long int*)(a)-1))&~3 - sizeof(long int*))

リンクされた回答では、これをデバッグのみに使用し、実際のコードに依存しないことを強くお勧めします。私はその警告を繰り返さざるを得ないと感じています。

于 2013-03-12T17:45:42.690 に答える
0

要求されたブロックのサイズをキャッシュするポインターのテーブルを構築するために、malloc にフックをインストールする必要があります。次に、解放するときに、malloc されたアイテムの以前のデータベースでポインターを検索します。

そうすれば、現在割り当てられているヒープの合計をどれだけ減らすかがわかり (それが目標の場合)、メモリにまだ保持されているヒープのすべての「領域」をリストする便利な場所があります。

于 2013-03-12T17:41:27.240 に答える