11

プログラミング言語: C プラットフォーム: ARM コンパイラ: ADS 1.2

melloc/freeプロジェクトで単純な呼び出しを追跡する必要があります。プログラムがすべてのリソースを割り当てたときに必要なヒープメモリの量について、非常に基本的な考えを得る必要があります。そのため、malloc/free呼び出しのラッパーを用意しました。これらのラッパーでは、 が呼び出されたときに現在のメモリ カウントをインクリメントし、が呼び出さmallocれたときにデクリメントする必要がありますfreemalloc呼び出し元から割り当てるサイズがあるので、ケースは簡単です。freeポインター/サイズのマッピングをどこかに保存する必要があるため、このケースをどのように処理するのか疑問に思っています。これは C であるため、これを簡単に実装するための標準マップはありません。

ライブラリへのリンクを避けようとしているので、 *.c/h 実装を優先します。

だから、私を導くかもしれない簡単な実装がすでにあるかどうか疑問に思っています。そうでない場合は、これが先に進んで実装する動機になります。

編集: 純粋にデバッグ用であり、このコードは製品に同梱されていません。

編集: Makis からの回答に基づく初期実装。これに関するフィードバックをいただければ幸いです。

編集: 再加工された実装

#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <string.h>
#include <limits.h>

static size_t gnCurrentMemory = 0;
static size_t gnPeakMemory    = 0;

void *MemAlloc (size_t nSize)
{
  void *pMem = malloc(sizeof(size_t) + nSize);

  if (pMem)
  {
    size_t *pSize = (size_t *)pMem;

    memcpy(pSize, &nSize, sizeof(nSize));

    gnCurrentMemory += nSize;

    if (gnCurrentMemory > gnPeakMemory)
    {
      gnPeakMemory = gnCurrentMemory;
    }

    printf("PMemAlloc (%#X) - Size (%d), Current (%d), Peak (%d)\n",
           pSize + 1, nSize, gnCurrentMemory, gnPeakMemory);

    return(pSize + 1);
  }

  return NULL;
}

void  MemFree (void *pMem)
{
  if(pMem)
  {
    size_t *pSize = (size_t *)pMem;

    // Get the size
    --pSize;

    assert(gnCurrentMemory >= *pSize);

    printf("PMemFree (%#X) - Size (%d), Current (%d), Peak (%d)\n",
           pMem,  *pSize, gnCurrentMemory, gnPeakMemory);

    gnCurrentMemory -= *pSize;

    free(pSize);
  }
}

#define BUFFERSIZE (1024*1024)

typedef struct
{
  bool flag;
  int buffer[BUFFERSIZE];
  bool bools[BUFFERSIZE];
} sample_buffer;

typedef struct
{
  unsigned int whichbuffer;
  char ch;
} buffer_info;


int main(void)
{
  unsigned int i;
  buffer_info *bufferinfo;

  sample_buffer  *mybuffer;

  char *pCh;

  printf("Tesint MemAlloc - MemFree\n");

  mybuffer = (sample_buffer *) MemAlloc(sizeof(sample_buffer));

  if (mybuffer == NULL)
  {
    printf("ERROR ALLOCATING mybuffer\n");

    return EXIT_FAILURE;
  }

  bufferinfo = (buffer_info *) MemAlloc(sizeof(buffer_info));

  if (bufferinfo == NULL)
  {
    printf("ERROR ALLOCATING bufferinfo\n");

    MemFree(mybuffer);

    return EXIT_FAILURE;
  }

  pCh = (char *)MemAlloc(sizeof(char));

  printf("finished malloc\n");

  // fill allocated memory with integers and read back some values
  for(i = 0; i < BUFFERSIZE; ++i)
  {
    mybuffer->buffer[i] = i;
    mybuffer->bools[i] = true;
    bufferinfo->whichbuffer = (unsigned int)(i/100);
  }


  MemFree(bufferinfo);
  MemFree(mybuffer);

  if(pCh)
  {
    MemFree(pCh);
  }

  return EXIT_SUCCESS;
}
4

7 に答える 7

13

ラッパーに数バイト余分に割り当てて、ID (malloc() と free() を結合できるようにしたい場合) またはサイズだけをそこに入れることができます。それだけ多くのメモリを malloc() し、メモリ ブロックの先頭に情報を格納し、返されたポインタをそのバイト数だけ前方に移動します。

これは、ところで、フェンス ポインター/指紋などにも簡単に使用できます。

于 2009-05-12T10:29:30.860 に答える
2

malloc/によって使用される内部テーブルにアクセスできるか(いくつかのヒントfreeについては、この質問: malloc() / free() は割り当てられたサイズとアドレスをどこで保存しますか?を参照してください)、またはラッパーで独自のテーブルを管理する必要があります。

于 2009-05-12T10:23:07.110 に答える
1

独自の実装をローリングする代わりに、いつでもvalgrindを使用できます。割り当てるメモリの量を気にしない場合は、さらに単純な実装を使用できます。初期サイズとサイズ変更などのために何らかの要因で増加しますが、アイデアは得られます.)

編集:これがARM用であることを見逃しました。私の知る限り、ARMではvalgrindを使用できないため、オプションではない可能性があります。

static size_t indexAllocedStorage = 0;
static size_t *pAllocedStorage = NULL;
static unsigned int free_calls = 0; 
static unsigned long long int total_mem_alloced = 0; 

void * 
my_malloc(size_t size){
    size_t *temp;
    void *p = malloc(size);
    if(p == NULL){
    fprintf(stderr,"my_malloc malloc failed, %s", strerror(errno));
    exit(EXIT_FAILURE);
    }

    total_mem_alloced += size;

    temp = (size_t *)realloc(pAllocedStorage, (indexAllocedStorage+1) * sizeof(size_t));
    if(temp == NULL){
        fprintf(stderr,"my_malloc realloc failed, %s", strerror(errno));
         exit(EXIT_FAILURE);
    }

    pAllocedStorage = temp; 
    pAllocedStorage[indexAllocedStorage++] = (size_t)p;

    return p;
}

void 
my_free(void *p){
    size_t i;
    int found = 0;

    for(i = 0; i < indexAllocedStorage; i++){
    if(pAllocedStorage[i] == (size_t)p){
        pAllocedStorage[i] = (size_t)NULL;
        found = 1;
        break;
        }
    }

    if(!found){
        printf("Free Called on unknown\n");
    }

    free_calls++;
    free(p);
}

void 
free_check(void) {
    size_t i;

    printf("checking freed memeory\n");
    for(i = 0; i < indexAllocedStorage; i++){   
        if(pAllocedStorage[i] != (size_t)NULL){
            printf( "Memory leak %X\n", (unsigned int)pAllocedStorage[i]);
            free((void *)pAllocedStorage[i]);
        }
    }

    free(pAllocedStorage);
    pAllocedStorage = NULL;
}
于 2009-05-12T12:17:50.133 に答える
0

rmallocを使用します。これは、メモリ使用量をデバッグするための単純なライブラリ(実際には2つのファイルのみ)ですが、統計もサポートしています。すでにラッパー関数を使用しているので、rmallocを使用するのは非常に簡単です。strdupなども交換する必要があることに注意してください。

于 2009-05-12T12:34:07.030 に答える
0

プログラムは、realloc()、calloc()、getcwd()(一部の実装ではバッファがNULLの場合にメモリを割り当てる可能性があるため)、およびコンパイラでサポートされている場合はstrdup()または同様の関数をインターセプトする必要がある場合もあります。

于 2009-05-12T13:12:28.287 に答える
0

このページに記載されているのと同じ手法をいくつか試してみて、Google 検索からここにたどり着きました。この質問は古いことは知っていますが、記録のために追加したかった...

1) オペレーティング システムには、実行中のプロセスで使用されているヒープ メモリの量を確認するためのツールが用意されていませんか? ARM について話しているようですので、これが当てはまる可能性があります。ほとんどのフル機能の OS では、これは cmd-line ツールを使用してヒープ サイズを確認するだけの問題です。

2) libc で利用可能な場合、ほとんどのプラットフォームで sbrk(0) がデータ セグメントの終了アドレスを教えてくれます。持っている場合は、プログラムの開始時にそのアドレスを格納するだけで (たとえば、startBrk=sbrk(0))、割り当てられたサイズはいつでも sbrk(0) - startBrk になります。

3) 共有オブジェクトを使用でき、libc に動的にリンクしていて、OS のランタイム ローダーに LD_PRELOAD 環境変数のようなものがある場合、実際の libc 関数を定義する独自の共有オブジェクトを構築する方が便利な場合があります。同じシンボル (MemAlloc() ではなく malloc()) を使用すると、ローダーが最初に lib をロードし、libc 関数を「挿入」します。dlsym() と RTLD_NEXT フラグを使用して実際の libc 関数のアドレスをさらに取得できるため、malloc/free ラッパーを使用するためにすべてのコードを再コンパイルする必要なく、上記の操作を実行できます。LD_PRELOAD=mymemdebug.so のような環境変数を設定して実行するプログラム (または最初の文の説明に適合する任意のプログラム) を開始するときの実行時の決定にすぎません。

于 2013-08-01T20:04:17.267 に答える
0

で実行している場合は、バイナリをvalgrindx86で実行するだけで、およびの標準実装を使用して、このすべての情報が収集されます。単純。mallocfree

于 2009-05-13T03:38:17.893 に答える