22.03.17メモリ

7000 ワード

メモリアドレス

  • 16進数表示
  • 16進数0 xで始まる(0 xFF)
  • .
  • メモリアドレスを受信する演算子:&
  • アドレスの値演算子:*
  • 特定値のメモリアドレスとは、メモリアドレスに割り当てる値
  • である.
  • は、ポッドキャストとしての変数を以下のように宣言することができる.
  • #include <stdio.h>
    
    int main(void)
    {
       int n = 50;
       int *p = &n;
       printf("%p\n", p);
       printf("%i\n", *p);
    }
  • pは、nのメモリアドレスを格納する「Pointer」である.
  • pはintデータ型の変数
  • を表す.

    文字列(String)

  • THERE IS NO STRING
  • 文字列s="EMMA"の場合、sは最終的にE(s[0])アドレスへのPotinterである.
  • 原名、char*s="EMMA".
  • typedef char*string:char*(charのアドレス)はstringとして宣言されます.
  • 文字列とは、charの最初のアドレスを覚え、最後に0で終わるルールです.
  • 文字列変数は、文字列のメモリアドレスを格納します.(char *s = "...")
  • #include <cs50.h>
    #include <ctype.h>
    #include <stdio.h>
    
    int main(void)
    {
        string s = get_string("s: ");
        string t = s;
    
        t[0] = toupper(t[0]);
    
        printf("s: %s\n", s);
        printf("t: %s\n", t);
    }
  • なので、このように設定すると、sのアドレス値がtという変数に書き込まれるので、tの最初の字を大文字に変更すると、sの最初の字も大文字になります.
  • このときに使用するのは「メモリ割当て関数」「malloc」です.
  • #include <cs50.h>
    #include <ctype.h>
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        char *s = get_string("s: ");
        char *t = malloc(strlen(s) + 1);
    
        for (int i = 0, n = strlen(s); i < n + 1; i++)
        {
            t[i] = s[i];
        }
    
        t[0] = toupper(t[0]);
    
        printf("s: %s\n", s);
        printf("t: %s\n", t);
    }
  • malloc()関数のパラメータでメモリサイズを設定できます.
  • の上の例では、0を考慮する必要があるため、入力された文字列の長さに+1を加えてパラメータに渡す.
  • およびnull終端子0にコピーするために、for構文をi
  • は簡単なstrcpy(t,s)である.このように表現することができます
  • メモリの割り当てと無効化

  • malloc : memory allocation. 割り当てられたメモリの最初のバイトアドレスを返します.
  • メモリ割当て:メモリの一部を取得し、その場所にPointerを指定します.
  • char *t = malloc(strlen(s) + 1);
  • メモリが割り当てられていますが、解放されていません.(必須>free無効)
  • free:割り当てられたメモリを返します.プログラムがより多くのメモリを使用するには、返さなければなりません.使用しないメモリは解除する必要があります.
  • メモリ検証デバッグにvalgrindが使用されています.
  • でメモリの漏洩を確認できます.関数の最後の行free(t);加えて解除しましょう.
  • freeを使用して無効にしない場合、メモリに格納されている値は「ゴミ値」です.
  • バッファオーバーフロー:割り当てられたメモリ領域を超えています.(例は以下の通り)
  • int *x = malloc(10 * sizeof(int));
    x[10] = 0;  // Buffer overflow에 해당함. 

    メモリ交換、Stack、Heap


    メモリにはデータストアがあります.
  • Machine code = compiled binary
  • グローバル変数=グローバル変数
  • Heap:malloc割り当てメモリの位置
  • スタック:関数呼び出し時の領域変数のスタックスペース(Bottom->Top)
  • main関数の変数はスタックに
  • 格納される.
  • ですが、メモリ構造はあまりよくありません.malloc呼び出しが多ければ多いほど、関数呼び出しが多ければ多いほど、heapとstackの領域が大きくなり、2つのメモリの領域がどこかで衝突します.
  • Heapオーバーフロー(mallocと呼び出し)&スタックオーバーフロー(関数と呼び出し)
  • ->Bufferオーバーフロー:画面が停止し、ファイルが開くか動作しません.
  • #include <stdio.h>
    
    void swap(int a, int b);
    
    int main(void)
    {
        int x = 1;
        int y = 2;
    
        printf("x is %i, y is %i\n", x, y);
        swap(x, y);
        printf("x is %i, y is %i\n", x, y);
    }
    
    void swap(int a, int b)
    {
        int tmp = a;
        a = b;
        b = tmp;
    }
  • swap関数はスタックにスタックされ、順次実行されると、完了すると破棄されます.(使用しない)
  • a,bはx,yの複製値を用いるので,主内のx,yは影響を受けない.(&a != &x, &b != &y)
  • 根本的な解決策:x、yのアドレスを教えて、swap関数をアドレスに移動させ、値を変更します.
  • すなわちswap関数のa,bは、x,yを「指す」必要がある.
  • #include <stdio.h>
    
    void swap(int *a, int *b);
    
    int main(void)
    {
        int x = 1;
        int y = 2;
    
        printf("x is %i, y is %i\n", x, y);
        swap(&x, &y);  // x, y의 메모리 주소를 넘겨줌
        printf("x is %i, y is %i\n", x, y);
    }
    
    void swap(int *a, int *b)  // 넘겨받은 주소를 a와 b에 저장
    {
        int tmp = *a;  // a 주소에 저장된 값을 *로 불러와서 tmp에 저장
        *a = *b;  // a 주소에 저장된 값을 b 주소에 저장된 값으로 변경 
        *b = tmp;  // b 주소에 저장된 값을 tmp 값으로 변경
    }

    ファイルの読み込み、書き込み

  • 変数の値を変更する場合は、値として渡すことはできません(コピーは渡され、消えています).アドレスをxに渡す必要があります.
  • scanf("%s", s); -> 保存するアドレスを転送します.arrayの場合、最初のバイトアドレスが受信されます.
  • #include <cs50.h>
    #include <stdio.h>
    #include <string.h>
    
    int main(void)
    {
        // Open file : FILE 이라는 새로운 자료형을 가리키는 포인터 변수 file
        FILE *file = fopen("phonebook.csv", "a");  // 파일 내용 저장 csv : comma seperated value
    
        // Get strings from user
        char *name = get_string("Name: ");
        char *number = get_string("Number: ");
    
        // Print (write) strings to file
        fprintf(file, "%s, %s\n", name, number);
    
        //Close file
        fclose(file);
    }
  • では、ポインタとメモリアドレスの概念が常に言及されます.