top of page

[C]関数から返したアドレスを後から参照すると値がおかしい


現象

C言語で関数(func_a)を作成。引数の内容をもとにある構造体のインスタンスを作成し、そのアドレスを返す。

そのアドレスはその後別の関数(func_b)の引数に使用。アドレスを参照し、func_aで作成した構造体の内容をもとに規定の処理を行う。

typedef struct {
  int a;
  int b;
}SAMPLE_STRUCT

SAMPLE_STRUCT* func_a(int a, int b){

  SAMPLE_STRUCT s;
  s.a = a;
  s.b = b;
  
  return &s;
}

void func_b(SAMPLE_STRUCT *smpl){

  int a =(*smpl).a;  //aの値がおかしい
}

func_bでメンバaの値を取り出すと、func_aで設定したのと異なる値が入っている。


問題:上記コードでどこがおかしいでしょう?



原因

答え:関数(func_a)のローカル変数として確保したアドレスを返しているから。

関数のローカル変数はスタックに取られる。そのアドレスを後から参照しても、スタックは別の関数でも使われているから、そのアドレスに格納されている値は順次変更される。



解決策

1 構造体そのものを返す

2 mallocなどでヒープに確保した変数のアドレスを返す

3 グローバル変数として確保した変数のアドレスを返す


SAMPLE_STRUCT* func_a(int a, int b){

  SAMPLE_STRUCT *s = 
  (SAMPLE_STRUCT *)malloc(sizeof(SAMPLE_STRUCT));
  s->a = a;
  s->b = b;
  
  return s;
}


最後に

メモリをちゃんと理解していないとこういうミスが起こるんですね

最新記事

すべて表示

[C]2次元配列のポインタを関数の引数で渡す

やりたいこと 2次元配列に作用する処理がある 処理の対象となる配列が複数ある このような場合、この処理は関数化したいが、引数をどう定義するのかちょっと迷った やり方 配列サイズは固定とすれば、以下のようにすればよい // Define a typedef for the...

[C]関数ポインタの配列

やりたいこと 掲題の通りだが、関数ポインタの配列を定義したい。 具体的にどう使うかというと、例えばpthread_createの第3引数は新規スレッドで実行したい関数のポインタを渡す。複数の関数に対してそれぞれ新規スレッドを割り当てる場合、それらのポインタを配列にしてまとめ...

Bình luận


カテゴリ

あなたの買い物をサポートする
アプリ Shop Plan

iphone6.5p2.png

​いつ何を買うかの計画を立てられるアプリです。

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png

靴を大切にしよう!靴管理アプリ SHOES_KEEP

納品:iPhone6.5①.png

靴の履いた回数、お手入れ回数を管理するアプリです。

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png

「後で読む」を忘れないアプリ ArticleReminder

気になった​Webサイトを登録し、指定時刻にリマインダを送れるアプリです

google-play-badge.png
Download_on_the_App_Store_Badge_JP_RGB_blk_100317.png
bottom of page