2

私はまだCでかなり錆びており、これを理解していません。私がやろうとしているのは、独自の malloc を実装して、割り当てを追跡し、free() への欠落した呼び出しをデバッグできるようにすることです。次のようなヘッダーがあります。

typedef struct MemoryInfo {
  mem_Kind kind;
  unsigned int id;
  struct MemoryInfo* prev;
  struct MemoryInfo* next;
} MemoryInfo;

そして、私のカスタム malloc は次のようになります。

void* my_malloc(mem_Kind kind, unsigned int size) {
  MemoryInfo* mem;

  allocCount++;
  mem = (MemoryInfo*)malloc(sizeof(MemoryInfo) + size);
  mem->id = id;
  mem->kind = kind;
  // set prev/next...

  return mem + sizeof(MemoryInfo); // return pointer to memory after header
}

しかし、私は明らかにポインター演算が間違っています。ただしvoid* memory、構造体の最後に a を追加して別の malloc を実行すると、うまくいくように見えますが、問題は、そうするとヘッダーが実際に見つからmy_freeないことです。基本的にヘッダーを先頭に追加しようとしているので、逆ポインター演算を実行してヘッダーを解放できます。

void my_free(void* memory) {
  MemoryInfo* mem = memory - sizeof(MemoryInfo); // not correct either
  allocCount--;
  free(mem);
}

ここで何が間違っていますか?

4

3 に答える 3

1

ポインタへの追加に問題があると思います。次のようにする必要があります。

return (char*)mem + sizeof(MemoryInfo); // return pointer to memory after header

void my_free(void* memory) {
  MemoryInfo* mem = (MemoryInfo*)((char*)memory - sizeof(MemoryInfo)); // not correct either
  allocCount--;
  free(mem);
}

ところで。このプログラムを見てください。

#include <stdio.h>

typedef struct MemoryInfo {
  int kind;
  unsigned int id;
  struct MemoryInfo* prev;
  struct MemoryInfo* next;
} MemoryInfo;



int main()
{
  MemoryInfo* ptr = 0;

  printf("sizeof: %d\n",sizeof(MemoryInfo));
  printf("%d\n",ptr+3);
  return 0;
}

MemoryInfo へのポインタに 3 を追加しましたが、その値は 3*sizeof(MemoryInfo) になります。

于 2012-05-12T16:45:39.633 に答える
0

あなたのポインター演算は間違っています。ptr+1+1 では、正しいインクリメント (sizeof *ptr) が既に使用されています。sizeof *ptrptr が char ポインターの場合はインクリメントする必要がありますが、そうではありません。

void *my_malloc(mem_Kind kind, unsigned int size) {
  MemoryInfo  mem;

  allocCount++;
  mem = malloc(sizeof *mem + size);
  mem->id = id;
  mem->kind = kind;
  // set prev/next...

  return mem + 1; // return pointer to memory after header
}


void my_free(void *memory) {
  MemoryInfo *mem = memory; // not correct either
  mem -= 1;
  allocCount--;
  free(mem);
}

また、malloc() とその仲間は、すべてのオブジェクトに適したポインターを返す必要があり、すべてのオブジェクトの自然な境界に合わせる必要があることを考慮してください。(これは、32 ビット、64 ビット、またはプラットフォームが指示するものである可能性があります) たとえば、 sizeof (int)==2 および sizeof (void*) == 8 の場合、サイズが失敗する可能性があります。(しかし、幸運なことに、これは非常にまれなケースのようです)

于 2012-05-12T17:04:49.953 に答える
0

良い習慣は次のように定義されます:

struct some_struct {
  size_t data_size;
  struct some_struct  *next, *prev;
  void * struct_data[];
}

そして私たちはそれを次のようにします:

struct some_struct *get_some_struct ( void *buf,size_t buflen,struct some_struct **next){
  *next=0;
  struct some_struct *s=(struct some_struct *)buf;
  if ( s && buflen < sizof(*s) + s->data_size )
    *next = (char*)s + s->data_size;
    return s;
  else
    return 0;
}

したがって、構造体を反復処理する必要がある場合は、バッファー内の次の構造体のオフセットを適切に取得できます。アプローチしてもらいたいだけです。お手に取って頂ければ幸いです

于 2012-05-12T18:05:59.127 に答える