C言語の静的なメモリと動的なメモリ

348, 2021-11-18

目次

静的な確保と動的な確保

C言語のメモリの話しです。
メモリには主に静的なメモリ動的なメモリがあります。

静的なメモリはプログラムのセグメントに保存されるメモリです。
スタックセグメントやデータセグメント、テキストセグメントがこれに当たります。

いっぽう動的なメモリはヒープから動的に取ってくるメモリです。
これはstdlib.hmalloc()calloc()関数を使ってメモリを確保します。

コードで見る場合、↓のコードでは静的なメモリを確保しています。

int a = 1;

動的なメモリ確保は↓のようになります。

int *a = calloc(1, sizeof(int));
free(a);

これらのメモリ確保についてその違いを認識しておくのは結構大事です。
高度なプログラムでは動的なメモリ確保を行うことが多くなるので、その方法を知っておくのは有用です。

どちらが速いか?

一般的に速いのは静的なメモリ確保だと思っていました。
しかし↓の記事の結果を見ると結果はどちらも変わらないようです

静的なメモリ(スタック)のほうがmalloc()などの関数も呼んでないし速いんじゃないか?!
となるわけですが、実験結果を見るとどうもそうでもないみたいです。

覆される自分の常識

しかし理屈ではmalloc()は内部で色々やってるわけですので、その分遅くなるというのが普通の考えだと思います。

どちらが使いやすいか?

静的なメモリはスコープが破棄されると自動的に破棄されます。
C言語ではブレースで作るブロックで自動変数の寿命をコントロールできます。

int a;
{
    int b;
    {
        int c;
    } // cはここまで
} // bはここまで

静的なメモリは自動で破棄されるので、メモリの解放もれということがありません。
そのため使いやすいと言えます。
ただし、メモリがそのスコープ内に束縛されるため、スコープの外に持ち出そうとすると面倒になります。
たとえば関数の中のローカル変数をポインタで関数の外に持ち出すということはできません。
あ、staticな変数はできますよ。

動的なメモリはmalloc()などでメモリを確保した場合、free()関数でメモリを手動で開放する必要があります。
これは言い換えればメモリの確保と解放をプログラマの好きなタイミングで行えるということになります。
しかし、メモリの解放忘れがあるとそれはメモリリークというバグになります。

メモリリークが多いプログラムは実行しているうちにメモリをどんどん消費してやがてOSからキルされることがあります。
そのため長時間稼働させたいプログラムではメモリリークと言うバグは結構致命的になります。

しかし動的なメモリは特定のスコープに束縛されないため自由です。
そのため関数から関数へポインタで移動することもできます。
柔軟性では静的なメモリより上と言えます。

どちらを使うべきか?

じつはこの記事を書く前は私は静的メモリのほうが速いと思っていました。
そのためしめくくりは「速度が必要なら静的メモリ、柔軟性なら動的メモリ・・・」としようと思ったのですが、あてが外れてしまいました。

動的メモリは柔軟性がありますがメモリリークのバグを生む場合があります。
静的メモリは柔軟性がありませんが勝手に破棄されます。
この2つの特性をよく認識して使うのが吉と言えます。

しかし、自分のプロダクトの速度改善で静的なメモリ確保の割合を増やそうと思ってたんですが、どうもその必要はなさそうだなぁ……。

プロファイリングしろし

ほんまやね