[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;
}
最後に
メモリをちゃんと理解していないとこういうミスが起こるんですね
最新記事
すべて表示概要 前回、コンパイルとリンクについて説明しました。 今回は、それを元にコンパイルエラーとリンクエラーについて説明します。 コンパイルエラー コンパイルで行われるのは 1 コードのバイナリ化 2 あるものリスト、欲しいものリストの作成 でした。これでエラーとなるのは以下のような場合です。 1 コードがバイナリ化できない(つまり構文が規則通りでない、など) 2 あるものリストが作れない(つまり関数の