は、私がmalloc
を使って、関数内の変数を作成しているとします関数内の変数mallocはどうなりますか?
i
に位置しています
int f()
{
int* i=(int*)malloc(sizeof(int));
/* ... */
}
?ヒープまたは機能でf()
スタック?
は、私がmalloc
を使って、関数内の変数を作成しているとします関数内の変数mallocはどうなりますか?
i
に位置しています
int f()
{
int* i=(int*)malloc(sizeof(int));
/* ... */
}
?ヒープまたは機能でf()
スタック?
i
という名前の変数はほとんどの場合整数なので、i
の代わりにp
を使用します。
void function(void) {
int *p = malloc(sizeof(*p));
}
二つのものがここにあります:以下の関係p
と*p
:
stack heap │ ... │ │ ... │ ┢━━━━━━━┪ ┢━━━━━━━┪ ┃ p ┃ ──→ ┃ *p ┃ ┡━━━━━━━┩ ┡━━━━━━━┩ │ ... │ │ ... │
あなたが関数から返されると、p
がなくなっています。ただし、*p
は、free()
に電話するまで割り当てられたままです。 free()
に電話を忘れると、*p
は使用できないのに(p
がなくなっているので)永遠に残るため、「メモリリーク」が発生します。
注:p
は必ずしもスタック上にあるわけではありませんが、それはふりをすることができます。それはレジスタに入れることも、完全に最適化することもできます。スタック上を移動することもできます。とにかく "スタック"と "ヒープ"という概念はすべて技術的に実装固有です。
i
はローカル変数であるため、コンパイラはスタックストレージを割り当てることができますが、これはシナリオに依存します。コンパイラ/オプティマイザがスタックを回避してレジスタを使用できる単純な使用例でも可能です。
この変数i
には、intサイズの空間の動的割り当てのアドレスに対応する数値が含まれています。
ほとんどのシステムでは、@Dietrich Eppの回答が問題をカバーしています。完全性のために、私は次のように追加したいと思います:
変数がどこに/どのように格納されているかは一般的な方法はありません。それは標準の一部ではありません。特定のシステムによって異なります。
c
にはスタックやヒープはありません。概念は、システム固有の実装の詳細です。
規格(ISO/IEC 9899)は、このような "保存期間" を指定:
6.2.4オブジェクトは、その寿命を決定する保存期間を有します。期間は、静的、自動、および割り当ての3つのストレージがあります( )。
標準には関連するルールが記述されていますが、標準ではその実装方法は気にしません。
ほとんどの実装ではstack
とheap
の使用が一般的ですが、それは必須ではありません。
質問は「私はどこですか?」と尋ねる。 Cの標準が質問に答えないと言っても、質問に答えることはできません。 (また、C11には4番目のストレージ時間が導入されていますが、実装は標準リリースよりずっと前です) –
@DietrichEppこれは唯一正しい解決策だと思います。しかし、それが積み重なっているか、どこかにあると言うと、間違いです。 'c'はスタックとヒープを持っているように見せかける間違いです。 – 4386427
経験の浅い開発者にとって、スタックオーバーフローは敵対的なエクスペリエンスとなります。厳密に技術的に正しい質問に答えることは、その敵意の主な要因です。質問者が答えからどのような情報を学びたいのか、そしてあなたの質問が質問者をその知識に近づけるのか、それともCの標準に関する知識を示しているのかを考えてみましょう。 –
変数は* iです。私たちはmallocなしでそこにいます。それはポインタです。
mallocは、ヒープ内の割り当てられたメモリの開始アドレスを返します。そして、=はあなたのポインタにこのアドレスを割り当てます。
あなたはこのポインタに0を割り当てるか、それに何でも割り当ててもよい(例えば4711)。しかし、あなたがアドレスを指しているメモリに読み書きしてアクセスすると、それはあなたのアドレスにはなく、あなたはセグメンテーションフォルトを取得します。
あなたは 'malloc'を使って変数を作成しません。あなたはそれでメモリを割り当てます。 –
あなたは 'malloc'を使って"関数の中に変数を作成 "していません。あなたの変数 'i'と' malloc'-edのメモリは、 'i'が最初にそのメモリを指し示すことを除いて、お互いに何の関係もありません。 – AnT
Cでは、ヒープメモリ割り当て関数から返される型は 'void *'で、他のポインタに代入することができます。返された型をキャストすることは効果がなく、コードを乱雑にしてしまいます。 I.戻り値をキャストしないでください。 – user3629249