ダイナミックメモリ割り当て[李園7舎_404]

4428 ワード

前回C言語をメモしたとき、C言語に関する異なるデータ変数タイプの格納方法をメモしました.変数の格納場所、メモリがいつ割り当てられるか、初期化されていないときの初期値、役割ドメイン、生存期間などの話題が含まれます.スタックのダイナミックメモリ割り当てに関する問題が残っています.授業の余暇にダイナミックメモリの割り当てとダイナミックメモリの割り当てを使用するときに注意しなければならない問題について話します.
ダイナミックメモリ割り当ての理由
  • スタック空間サイズ有限
  • これは主に大きなプログラムに現れている.動的ローカル変数はスタックに格納され、スタックの空間は限られており、プログラムが大きすぎると変数を格納するために追加の空間が必要になります.このとき,スタックに動的メモリ,すなわち動的メモリ割り当てを要求することができる.
  • は、あるファイルなどのデータに必要なメモリサイズに応じたメモリ空間を申請し、空間の浪費を回避し、同時に空間の不足を回避する.

  • データの大きさが分からない場合は、大きな下付きスケールで対応するデータを格納する配列を定義します.これにより、この下付きスケール値が大きくなく、配列の境界を越えたり、下付きスケール値が大きすぎたりして、メモリが浪費されたりする可能性があります(対応するブロックが終了してから自動的に解放されます).
  • は、メモリ領域をスタックすることなく、対応する領域を手動で解放することができる(スタック上のデータは、対応するブロックの実行が終了するまで解放されない)
  • .
     
    動的メモリ割り当ての方法
    動的割り当てを行うオブジェクトは一般にポインタ(C言語)であり、malloc、calloc、realloc関数を使用してメモリ(スタック)空間を申請することができる.もちろん、メモリが不要になるまでfree関数を手動で使用して対応するスペースを解放する必要があります.メモリが漏洩しないようにします.
    1.malloc、calloc、reallocの違い
    void* realloc(void* ptr, unsigned newsize);
    void* malloc(unsigned size);v
    oid* calloc(size_t nelem, size_t elsize);
    3つの関数はstdlibにあります.h関数ライブラリ
    mallocとcallocの違いは1ブロックとnブロックの違いです.malloc呼び出し形式は(タイプ*)malloc(size):メモリのダイナミックストレージ領域に「size」バイトの長さの連続領域を割り当て、その領域のヘッダアドレスを返します.calloc呼び出し形式は(タイプ*)calloc(n,size):メモリのダイナミックストレージ領域にnブロック長が「size」バイトの連続領域を割り当て、ヘッダアドレスを返す.reallocは、再割り当て後のメモリ領域と元のメモリ領域が同じメモリアドレスを指すことを保証することはできません.返されるポインタは、新しいアドレスを指す可能性があります.
    mallocで簡単な例を挙げて、その基本的な使い方を説明します.
    例malloc_1.c
    #include 
    #include 
    #include 
    
    #define N       5
    
    int main(void)
    {
            int i;
            char *p;
    
            p       = (char*)malloc(N * sizeof(char));
    
            //Note: check return value of malloc funciton
            if(p == NULL){
                    printf("RAM allocate fialed
    "); return 0; } //memset(p, '1', N * sizeof(char)); //Look p[] values before initilized //and see address of everyone for(i = 0; i < N; i++){ printf("p[%d] no_value:%c\taddress is %p
    ", i, p[i], &p[i]); } //Release free(p); return 0; }

    コンパイルおよび実行結果:
    gcc -Wall malloc_1.c -o malloc_1 && ./malloc_1
    p[0] no_value:  address is 0x9e7f008
    p[1] no_value:  address is 0x9e7f009
    p[2] no_value:  address is 0x9e7f00a
    p[3] no_value:  address is 0x9e7f00b
    p[4] no_value:  address is 0x9e7f00c
    

    プログラムにより、スタックに存在するローカルポインタ変数は、スタック内のN*sizeof(char)バイトサイズのメモリを指し、このメモリは初期化されていない(格納された文字を指定する).実行結果から、malloc関数を用いて割り当てられたメモリの初期値(p[i])は不定(mallocをint、floatを用いて空間を割り当てる場合、p[i]の値は0,0.000000)であり、対応するデータに割り当てられたアドレスは連続している(char型データは1バイトを占め、メモリは1つの記憶ユニット(バイト)でアドレスされている).
    プログラム中のmemset(p,'1',N*sizeof(char))前のコメントを削除すると,再コンパイル実行の結果は次のようになる.
     gcc -Wall malloc_1.c -o malloc_1 && ./malloc_1
    p[0] no_value:1 address is 0x852b008
    p[1] no_value:1 address is 0x852b009
    p[2] no_value:1 address is 0x852b00a
    p[3] no_value:1 address is 0x852b00b
    p[4] no_value:1 address is 0x852b00c
    

    malloc関数で申請された空間が初期化されずに使用された後のエラーを回避するために、memset()関数を使用して各バイトを初期化することができる.
    注意:プログラム内のcharタイプのデータは1バイトのメモリしか占めていないため、データ出力は初期化値と同じです.他のデータ型(intなど)が複数バイト(4個)を占める場合、int全体の値をバイナリ上位に並べ替える
    例memset_1.c
    malloc_1.cでcharをintで置き換え、memset(p,'1',N*sizeof(char))のパラメータ'1'を1(パラメータcharをintに置き換える)に変更し、printf(「p[%d]no_value:%ctaddress%p」,i,p[i],&p[i]);の%cシフト%x.
    コンパイル実行:
    gcc -Wall memset_1.c -o memset_1 && ./memset_1
    p[0] no_value:1010101   address is 0x90b8008
    p[1] no_value:1010101   address is 0x90b800c
    p[2] no_value:1010101   address is 0x90b8010
    p[3] no_value:1010101   address is 0x90b8014
    p[4] no_value:1010101   address is 0x90b8018
    

    出力結果をよく見ると、memset関数の機能記述に従って、値をバイナリ形式で各バイトに格納し、1つの整形データが4バイトを占めるため、1つの整形データを出力すると、4バイトのデータを上位から下位に並べて32ビットを形成し、1つの整形データの値を得ることができる.後続のアドレスは、1つの整形データが4バイト(バイト単位でアドレス)を占めることを示している.
     
    必要なメモリが不要な場合は、free(p)を適時に使用して申請したスタックスペースを解放しなければならない.スタックのスペースにはプログラマ(プログラムを作成する人~~)が手動で解放する必要があるため、以前に割り当てられたメモリの1枚が使用されなくなったりアクセスできなくなったりしたが、それを解放しなかった場合、そのプロセスにとって、総利用可能なメモリの減少を招き、メモリ漏れが発生する.
     
    サブヒープ空間データ記憶図:
    もちろん、これはスタックにデータが格納されていることを示すだけでなく、データ格納はバイト単位でデータ変数タイプが占めるバイト数に応じて高いアドレスまたは低いアドレスに格納されていると思います.