Upgrade to Pro — share decks privately, control downloads, hide ads and more …

mallocしただけでメモリが確保できるって本当ですか?

MakKi
February 21, 2019

 mallocしただけでメモリが確保できるって本当ですか?

updated at 2019/Jun/29

MakKi

February 21, 2019
Tweet

More Decks by MakKi

Other Decks in Technology

Transcript

  1. mallocしただけで
    メモリが確保できるって
    本当ですか?
    KLab株式会社 牧内大輔

    View full-size slide

  2. 自己紹介
    ● 牧内大輔
    ○ Twitter: @makki_d
    ○ Github: makiuchi-d
    ● KLab株式会社
    ○ エンジニアリングマネージャー
    ○ スマホ向けオンラインゲームの会社
    ● 特徴
    ○ Linux使い(Kubuntu + Compiz)
    ○ 仕事:オンライン対戦のネットワーク基盤とか
    ○ 趣味:バーコード/QRコードライブラリをGoに移植

    View full-size slide

  3. 今日はmallocの話をします

    View full-size slide

  4. C言語触ったことある人

    View full-size slide

  5. mallocが何か知っている人

    View full-size slide

  6. mallocについて
    ● C標準ライブラリの関数
    ● メモリの動的割り当て
    #include
    void *malloc(size_t size);

    View full-size slide

  7. mallocの使い方
    ● こんなコードを見たことがあると思います
    void *p = malloc(1000);
    if(p == NULL){
    // メモリ確保失敗の処理
    ...
    }

    View full-size slide

  8. このプログラムを
    見てください

    View full-size slide

  9. #define TARGET_GB 20
    #define PAGE_SIZE 4096
    #define ONE_GB (1 * 1024 * 1024 * 1024)
    int main()
    {
    char *ptrs[TARGET_GB] = {NULL};
    int total_gb = 0;
    int i;
    printf("start. pid=%d", getpid());
    getchar();
    for(i=0; iptrs[i] = (char *) malloc(ONE_GB);
    if(ptrs[i] == NULL){
    printf("malloc returns NULL\n");
    break;
    }
    total_gb++;
    printf("malloc: p[%d] = %p", i, ptrs[i]);
    getchar();
    }
    printf("total %d GB allocated", total_gb);
    getchar();
    for(i=0; iint t;
    for(t=0; tptrs[i][t] = 0;
    }
    printf("touch %d GB", i+1);
    getchar();
    }
    for(i=0; ifree(ptrs[i]);
    }
    return 0;
    }

    View full-size slide

  10. #define TARGET_GB 20
    #define PAGE_SIZE 4096
    #define ONE_GB (1 * 1024 * 1024 * 1024)
    int main()
    {
    char *ptrs[TARGET_GB] = {NULL};
    int total_gb = 0;
    int i;
    printf("start. pid=%d", getpid());
    getchar();
    for(i=0; iptrs[i] = (char *) malloc(ONE_GB);
    if(ptrs[i] == NULL){
    printf("malloc returns NULL\n");
    break;
    }
    total_gb++;
    printf("malloc: p[%d] = %p", i, ptrs[i]);
    getchar();
    }
    printf("total %d GB allocated", total_gb);
    getchar();
    for(i=0; iint t;
    for(t=0; tptrs[i][t] = 0;
    }
    printf("touch %d GB", i+1);
    getchar();
    }
    for(i=0; ifree(ptrs[i]);
    }
    return 0;
    }
    1GBずつ20回malloc
    失敗したらbreak
    確保できたらアドレスを表示
    確保した合計を表示
    確保した領域に書き込み
    書き込んだ領域のサイズ表示
    メモリ解放

    View full-size slide

  11. 問題:何GB確保できるでしょうか
    ● このPCについて
    ○ Kubuntu 18.04 64bit (Linux version 4.15.0-54-generic)
    ○ 物理メモリ 16GB
    ■ ただし、VRAM領域もあるので実質約15.5GB
    ○ スワップ領域 2GB
    1. 15 GB
    2. 17 GB
    3. 20 GB

    View full-size slide

  12. 動かしてみます

    View full-size slide

  13. 結果
    ● 20GBまでmalloc成功
    ● この段階ではメモリ使用率は増えていない
    ● 確保したメモリに書き込んではじめてメモリ使用率増加
    ● 16GBに到達する前にOOM-Killerによって強制終了

    View full-size slide

  14. なぜこうなったのか

    View full-size slide

  15. 仮想アドレス空間
    ● プロセスから見えるメモリアドレス空間
    ○ ひと塊の大きなメモリに見える
    ○ 物理メモリの大きさとは無関係
    ● プロセス毎に独立
    ○ 他プロセスのメモリにアクセスできない
    ● 物理メモリとのマッピングはOSが管理
    ○ CPUの機能(MMU)を利用
    物理メモリ
    仮想アドレス

    View full-size slide

  16. mallocしたとき
    ● 仮想アドレス空間を予約
    ○ このアドレスが戻り値
    ● 物理メモリへのマッピングはまだしない
    ○ メモリ使用量は増えない
    物理メモリ
    仮想アドレス

    View full-size slide

  17. 書き込みしたとき
    ● このとき初めて物理メモリにマッピング
    ○ メモリ使用量増加
    最終的に物理メモリが足りなくなり
    メモリを開放するために
    プロセスが殺されました(OOM-Killer)
    物理メモリ
    仮想アドレス

    View full-size slide

  18. まとめ
    ● mallocしただけでは物理メモリは確保されない
    ● 戻り値チェックだけではメモリ不足を防げない
    ● 大量にメモリを使うプログラムを書くときは気をつけましょう
    ● 裏には複雑な仕組みが隠れていてコンピュータっておもしろい!

    View full-size slide

  19. 参考文献とか
    ● [試して理解] Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識
    ○ 竹内 覚、2018、技術評論社
    ○ ISBN: 978-4774196077
    ※今回のmallocの挙動は、glibcのmallocにおいて
     heapではなくpageからメモリ確保する場合のものです。
    ※mallocはもっと複雑なことをやっているので、
     興味のある人は小崎先生の動画を見ましょう。
     https://www.youtube.com/watch?v=0-vWT-t0UHg

    View full-size slide