質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

8回答

14043閲覧

C言語 - free関数の仕組み

Tia_66

総合スコア11

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

0クリップ

投稿2018/03/04 21:34

編集2018/03/04 21:36

疑問に思っている点

c言語のfree関数の動作の仕方

該当のソースコード

C

1int main(void) { 2 int *heap; 3 heap = (int *)malloc(256); 4 *heap = 123; 5 printf("%d\n",*heap); 6 free(heap); 7 printf("%d\n",*heap); 8 return 0; 9 }

###実行結果
123
123

###質問内容
なぜfree関数で開放した後でも値が出るのでしょうか。
まだ勉強し始めて間もない初心者なので詳しく教えていただけると助かります。
よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答8

0

"たまたま"です。

そもそもfreeした領域を読み出すことに意味はない。
もう"要らない"からfreeしたんでしょ?
ソコの値がどうであれ気にすることじゃない。

投稿2018/03/04 22:59

episteme

総合スコア16614

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tia_66

2018/03/05 14:04

値が残っていると無駄なメモリが消費されているのではないか、と思ったからです。 大きなプロジェクトになるとこの部分などが原因で動作が重くなるのではないかと思いました。
episteme

2018/03/05 22:55

心配に及ばず。必要に応じて再利用されますから。
gm300

2018/03/07 04:16

開放しても、物理的なRAMが無くなるわけじゃないので。 駐車場を借りて、返しても、その土地がなくなるわけじゃない。見えるだけではなく、自分のものじゃなくても車止めることもできる。
Tia_66

2018/03/21 23:05

再利用されるのですね なるほど 理解できました ありがとうございました
guest

0

解放したと言うことは、「以降のmallocで割り当て可能な領域」として登録されること。それだけでそこの値はいちいち消去されないためです。

投稿2018/03/04 21:45

a_saitoh

総合スコア702

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tia_66

2018/03/05 14:18

上書き可能な状態にした、というような捉え方でいいのでしょうか?
a_saitoh

2018/03/06 03:47

あなたの使用したfreeがそういう実装になっている考えてもらって構いません。ただ、「次のmallocで割り当てられ使われるまでは以前の内容が残っている」が保証されているわけではありません。
Tia_66

2018/03/21 23:06

なるほど 理解できました ありがとうございました!
guest

0

偶然あなたの使っているCライブラリの実装がそうなっているだけです。

freeは、渡されたアドレスがmalloc/realloc/callocで割り当てられたアドレスである場合その後の割当に使用できるようにします。
が、
mallocは、freeで解放されたアドレスを使いまわすとはなっていません。

よって、怠惰で富豪なfreeは何もしません。
故意か偶然かは知りませんが、解放後にメモリアクセスをしてしまうバグで予想外の事にはなりづらいです。

ちゃんとメモリをクリアして割当てた領域外への書き込みをしていた形跡がないかまで検査する実装もあります。

自分でmalloc/freeっぽいのを実装して使い回しを行い、メモリクリアを行わなかったせいで大問題になった例もあります。

投稿2018/03/04 23:41

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tia_66

2018/03/05 14:16

環境によって異なるのですね。 使うかもしれないし使わないかもしれないということですかね。 ご丁寧な回答ありがとうございました。
guest

0

適当に確保する量を増やしてみます。

int main(void) { int *heap; heap = (int *)malloc(256*1024*1024); *heap = 123; printf("%d\n",*heap); free(heap); printf("%d\n",*heap); return 0; }

256MB確保・解放すると私の手元の環境(CentOS7 gcc4.8.5)では

[vagrant@localhost ~]$ ./a.out 123 Segmentation fault

と読み取りに失敗しました。
大きなメモリを確保する際に内部の確保済みメモリを使わずにOSからメモリを受取り
解放時にはそのままOSへ返却する実装は多いと予測できます

投稿2018/03/05 16:01

asm

総合スコア15147

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tia_66

2018/03/05 16:15

別環境での実行結果を知ることができて良かったです。 ありがとうございました。
rubato6809

2018/03/06 01:46

別環境の実行結果ということなら、gcc 5.4.0 の実行結果をお見せします。 $ ./a.out 123 -1499264136 質問者と同じ256バイトのメモリをmalloc(), free()しました。メモリは無くなりませんが、free()しただけでメモリの値が上書きされたことを示しています。free()の実装が違うからでしょう。free()したが最後、そのメモリは「他のプログラム・他の関数が、他の用途に使うもの」になるのです。free()後も123が表示できたのは、 ・メモリが無くならない ・メモリが上書きされていない という条件が重なった、たまたま運が良かった場合に限るわけです。
rubato6809

2018/03/06 01:49 編集

(何故か同じコメントが投稿されてしまったので、削除します)
rubato6809

2018/03/06 01:49 編集

(これも削除)
Tia_66

2018/03/21 23:04

理解できました! ありがとうございました
guest

0

freeは確保されたメモリブロックを解放するだけで、初期化などは行わないためです。

投稿2018/03/04 21:55

hichon

総合スコア5737

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tia_66

2018/03/05 14:18

メモリの確保<->開放の関係なのですね。 ご回答ありがとうございました。
guest

0

ベストアンサー

メモリの確保、開放、といってもそのエリアをメモリ管理機構(?)に登録するか登録解除するか、だけの話でしかないです。
登録解除するときに、わざわざそのエリアをクリアするわけでもないので、解除直後はデータはそのまま残ったままです。
が、そのデータはいつ破壊されても文句は言えないってことですねー

投稿2018/03/04 21:49

y_waiwai

総合スコア87774

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tia_66

2018/03/05 14:09

メモリの確保<->開放なんですね。 値の登録<->解除のような捉え方をしていました。 丁寧なご回答ありがとうございました。 助かりました。
guest

0

解放されたからといっても、古い値が残っていることはあり得ます。また、C言語の仕様上「未定義の状態」となったからといってエラー停止するとも限りません。「バグの結果、意図通りの動作をする」ということも実際はかなりあります(大抵、後になってから大騒ぎする)

自分の場合**「free後は直ちに当該ポインタ変数にNULLを代入する」**と心がけています。

投稿2018/03/05 12:30

HogeAnimalLover

総合スコア4830

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tia_66

2018/03/05 14:13

なるほど。 これがバグ等の原因にもなり得るのですね。 NULLの代入の大切さがわかりました。 今後はNULLの代入を心がけようと思います。 ご回答ありがとうございました。
Tia_66

2018/03/05 14:22

続けてすみません。 もしNULLを代入する場合 int *heap; heap = (int *)malloc(256); *heap = 123; free(heap); *heap = NULL; このような記述でいいのでしょうか?
episteme

2018/03/05 20:10 編集

一旦freeしたらそこ(*heap)に書き込んじゃダメ。 正しくは free(heap)のあと heap = NULL;
Tia_66

2018/03/21 23:04

なるほど 理解できました! ありがとうございました
guest

0

有名な例え話ですが。

1,あなたはホテルで部屋を借りました。 (malloc)
2,あなたはベッドサイドテーブルの一番上の引き出しに本を置き、眠ります。
3,あなたは翌朝チェックアウト(free)しますが、部屋の鍵(ポインタ)を返却するのを忘れてしまいます。
4,一週間後、部屋の鍵があったので、ホテルの部屋に忘れ物(本)を取りに行きました。
5,ホテルの部屋を鍵で開けるとまだ清掃されていなのか、忘れ物が残ってました。

要点は1点
チェックアウト(free)したあとに部屋の鍵(ポインタ)を使ってはいけません。

投稿2018/03/05 10:44

編集2018/03/05 10:58
umyu

総合スコア5846

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Tia_66

2018/03/05 14:14

なるほど。 使える場合もあるがバグ等を考えた場合使うべきではない、ということですね。 わかり易い回答ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問