c言語のメモリ管理についての質問です。
以下のような関数をmain関数から呼び出して、内部でcallocを使って変数aにメモリを割り当てた場合、この関数からリターンした後もaというローカル変数の値はプログラムの実行終了までメモリ上に存在し続けることが保障されるという認識であってますでしょうか?
ご回答よろしくお願いいたします。
c
1 void a() { 2 int *a = calloc(1, sizeof(int)); 3 *a = 12; 4 return ture; 5 }
以下追記
例えばTokenという構造体があったとして、new_tokenという関数の中でこのようにtokという変数のメンバに値を代入したとします。
この時このnew_tokenという関数からreturnした後も、プログラムが終了するまで、この代入した値はメモリ上から失われないという認識は正しいでしょうか?
c
1struct Token { 2 Token *next; 3 int val; 4 char *str; 5 }; 6 7Token *new_token(Token *cur, char *str) { 8 Token *tok = calloc(1, sizeof(Token)); 9 tok->str = str; 10 tok->next = NULL; 11 cur->next = tok; 12 return tok;
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答5件
0
C
1Token *tok = calloc(1, sizeof(Token));
callocは,
あなたが要求したサイズ( sizeof(Token)
[byte]の塊を 1
個並べることができるだけのサイズ)の領域をメモリ上のどこかに割り当てて(さらにその領域をゼロ埋めして),その位置を戻り値として返す.
freeを用いて解放するまで,あなたはこの領域を正当に使用することができる.
……というだけ.
なので,
その領域を以降も使うためには(freeを用いるためにも),その領域の場所(callocが返してきた値)をどこかに覚えておく必要がある.
↓
そのためにあなたがやるべきことは,
【領域の場所覚えておくための「どこか」の生存期間 >= この領域を使用する期間】
となるように頑張ること.
- 質問文の最初コードでは,この「どこか」が関数内のローカル変数だったので,すぐに寿命が尽きてしまっている.
これではその領域を以降に使ったり解放するための手立てがなくなっている.
- 追記された後者側のコードでは関数呼び出し側がこのあたりをうまいことやるべき,ということになる.
投稿2021/07/09 06:25
総合スコア11996
0
前半の関数a
については、回答が付いているとおりで、間違っています。
メモリの実態と、そこへのポインターの混同があるのでは?
後半の追記部分は、代入先はプログラム終了もしくは、free
等で解放するまで残るというのは合っていますが、「tokという変数のメンバに値を代入したとします。」は間違いで、tok
という変数にメンバーは無くて、tok
という変数の指す先の構造体のメンバーに値を代入しています。
構造体と構造体を指すポインターの混同があるのでは?。
関数new_token
の返り値のポインターをどこかに保存しておけば、そのポインター経由で、構造体にアクセスできますし、ポインターの値を失ってしまえば、その構造体はメモリ上に存在はするがアクセスできないことになります。
投稿2021/07/09 05:33
総合スコア85901
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
ベストアンサー
以下のような関数をmain関数から呼び出して、内部でcallocを使って変数aにメモリを割り当てた場合、この関数からリターンした後もaというローカル変数の値はプログラムの実行終了までメモリ上に存在し続けることが保障されるという認識であってますでしょうか?
保証はされません。あくまで「結果的に」あるだけです。
保証はされるようです。
// ですが、あれを保証すると言うのかな……(まあ、確かに保証はしていますが……)
まず、普通の変数や定数はスタック領域に確保されます。
ですが、C言語でいうmalloc/free, C++でいうnew/delete でやる動的確保については、
ヒープ領域に確保されます。
スタック領域では一気に確保するので、大きいサイズは不可能です。
ヒープ領域では動的に確保するので大きいサイズでもOKです。
(メモリが許せば)
ただし、ヒープ領域にセットされたものはC言語でいう free関数, C++でいうdelete で破棄しないと、
破棄されません。
例えばTokenという構造体があったとして、new_tokenという関数の中でこのようにtokという変数のメンバに値を代入したとします。
用語がめちゃくちゃ。
C
1Token *tok;
はあくまでToken構造体のオブジェクトでしかないです。(近いニュアンスとしては『変数』か。厳密には違うけど)
ご指摘を受けて、よくよく考えると「ポインタ」なので、『Token構造体の(実体に対する)ポインタ』ですね。
メンバっていうのは Token構造体の中にある int val とかです。
この時このnew_tokenという関数からreturnした後も、プログラムが終了するまで、この代入した値はメモリ上から失われないという認識は正しいでしょうか
上で述べた通り、「明示的に破棄するまでは存在する」という意味では正しいです。
ですが、保証はされていません。
結果的に存在しているだけです。
ただし、質問にある、一番上のコードでは「他の関数からはアクセスできない」状態で居座っています。
[追記1]
リスト構造や木構造のように、「次へのポインタ」とかを持っている場合はそこから辿ればいいので、
使えます。
ポインタはあくまで「アドレス」です。
メモリ上のどこに配置されているかのアドレスであって、実体ではないので、
そのアドレスを辿っていけば使えるのです。
※ 他に低評価になりそうな理由があれば、挙げてほしいです。(後学のためにも)
投稿2021/07/09 05:19
編集2021/07/09 08:16総合スコア4962
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/07/09 05:47
2021/07/09 06:07
2021/07/09 06:10
2021/07/09 06:20
2021/07/09 06:35
2021/07/09 06:48
2021/07/09 06:58
2021/07/09 07:23
2021/07/09 07:48
2021/07/09 07:52
2021/07/09 08:11 編集
2021/07/10 03:06
2021/07/10 03:14
0
malloc/calloc/realloc された領域は free されぬ限り居座り続けます。
なのでこんなコード書いちゃダメ。呼び出されるたびにメモリをぢわぢわ食い潰します。
aというローカル変数の値はプログラムの実行終了までメモリ上に存在し続けることが保障されるという認識であってますでしょうか?
マチガイ。callocで確保された領域は居座ります。
が、その領域を指すaは関数から抜けたとたんに消えてなくなります。
結果確保された領域がどこだかわかんなくなるので開放できなくなります。
投稿2021/07/09 03:27
編集2021/07/09 03:46総合スコア16612
0
aというローカル変数の値はプログラムの実行終了までメモリ上に存在し続けることが保障されるという認識であってますでしょうか?
合っていません。a
というポインタ変数はこの関数が終われば寿命を迎えます。
*a
で指すメモリは、解放する(あるいはプログラムが終了する)まで保持されます。
投稿2021/07/09 03:25
総合スコア146018
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/07/09 07:18