-1

次のように temp.h で宣言された構造体があるとします。

/* physical memory */
typedef struct pmem_struct {
 uint32_t val;
} pmem_s, *pmem_p;

そして、メソッド pmem_p pmem_new() の temp.c ファイルでこの構造体を次のように宣言するとしましょう。

 pmem_p pmem_new() {
  pmem_s pmems;
  pmem_p pmem = &pmems;
  pmem->val = 0;
  //printf(stderr, "From Mem: %x\n", pmem->val);
  return pmem;
}

ここに私のmain.cファイルがあります:

#include <stdio.h>

#include "temp.h"
#include "gen.h"

int main() {
    pmem_p pmem = pmem_new(); /* create some physical memory */
    fprintf(stderr, "From Mem: %x\n", pmem->val);
......
}

pmem_new() の fprintf 行のコメントを外さない限り、この fprintf がFrom Mem: 4019cff4を出力するのはなぜですか。どちらもFrom Mem:0を正しく出力します。

4

1 に答える 1

4

pmem終了後に有効なメモリ領域を指しなくなったためですpmem_new()。あなたが見ているのは未定義の動作です。

 pmem_p pmem_new() {
  pmem_s pmems;
  pmem_p pmem = &pmems;
  pmem->val = 0;
  //printf(stderr, "From Mem: %x\n", pmem->val);
  return pmem;
}

pmemsここでは、関数のスコープ内の「スタック」に割り当てますpmem_new()。「スタック割り当て」では、プログラムが周囲のスコープを離れるとメモリが無効になります。したがって、へのポインターは、関数を終了した後pmemsダングリング ポインターpmem_new()になります。

「ヒープ」にメモリを割り当てることで解決できます。手動で行わない限り、メモリは破壊されません。C では、これは次のmallocメソッドによって行われます。

pmem_p pmem_new_correct() {
  pmem_p pmem = malloc(sizeof(*pmem));
  pmem->val = 0;
  return pmem;
}

ただし、このポインターを解放することを忘れないでください。解放しないと、メモリ リークが発生します。

int main() {
  pmem_p pmem = pmem_new();
  fprintf(stderr, "From Mem: %x\n", pmem->val);
  ......
  free(pmem);
}

(スタックとヒープについては、スタックとヒープとは何ですか?も参照してください。)

于 2012-09-28T13:48:12.580 に答える