読者です 読者をやめる 読者になる 読者になる

ソフトウェアエンジニア現役続行

雑多なことを綴ります

関数内でmallocするときの注意

関数内でmallocするときは、割り当てたアドレスの値を返すようにしなければなりません。

僕もやってしまったことがあるのですが、よくありがちなミスとしては以下のようなものがあります。

#include
#include

void alloc_func (char *ptr)
{
  ptr = malloc (512);
}

int main (void)
{
  char *ptr;
  alloc_func (ptr);
  free (ptr);
  return 0;
}

これを実行するとセグメンテーション違反で異常終了します。

原因を調べるために、以下のようにptrに格納されているアドレスの値を出力する処理を加えて実行してみます。

#include
#include

void alloc_func (char *ptr)
{
  printf ("before malloc : %p\n", ptr);
  ptr = malloc (512);
  printf ("after malloc : %p\n", ptr);
}

int main (void)
{
  char *ptr;
  printf ("before alloc_func : %p\n", ptr);
  alloc_func (ptr);
  printf ("after alloc_func : %p\n", ptr);
  free (ptr);
  return 0;
}

これを実行すると以下のような標準出力が得られます。

before alloc_func : 0x1e5940
before malloc : 0x1e5940
after malloc : 0x95cb008
after alloc_func : 0x1e5940

alloc_func関数内でptrにはmallocで得られたメモリの先頭アドレスが格納されますが、これがmain関数に戻ったときに保持されていないのが分かります。

これはコンパイルエラーにならないので、原因がすぐに分かりにくいやっかいな問題です。僕もこの手のミスでハマってしまい、原因究明にかなり時間をかけてしまった苦い思い出があります。

これを避けるために、関数内でmallocするときは、割り当てたアドレスの値を返すようにしなければなりません。例えば以下のようにします。

#include
#include

char *alloc_func (void)
{
  char *ptr = malloc (512);
  return ptr;
}

int main (void)
{
  char *ptr;
  ptr = alloc_func (void);
  free (ptr);
  return 0;
}