MALLOC(3) FreeBSD ライブラリ関数マニュアル MALLOC(3)
名称
malloc, calloc, realloc, free, reallocf − 汎用のメモリ割り当てのための関 数群 |
ライブラリ
標準 C ライブラリ (libc, −lc) |
書式
#include <stdlib.h> void * |
malloc(size_t size); void * |
calloc(size_t number, size_t size); void * |
realloc(void *ptr, size_t size); void * |
reallocf(void *ptr, size_t size); void |
free(void *ptr); char * malloc_options; |
解説 |
malloc() 関数は、 size バイトのメモリを割り当てます。割り当てられた空間は (可能なポインタ強制の後で) あらゆるタイプのオブジェクトが保存できるように 適切に調整されます。その空間の長さが少なくとも pagesize バイトである場合 ( getpagesize(3) 参照)、返されるメモリはページ境界が調整されていることで しょう。 malloc() に失敗すると、 NULL ポインタが返されます。 通常 malloc() が返すメモリは、0 のバイトで初期化されては いないことに注意 してください。 calloc() 関数は、 number 個の、長さが size であるオブジェクトに空間を割り 当てます。この関数を呼び出した結果は、割り当てられたメモリが 0 のバイトに 明示的に初期化されていることを除けば、引数 ‘‘number * size’’ で malloc() を呼び出した結果と同じです。 realloc() 関数は、 ptr で参照される、以前に割り当てられたメモリのサイズを size バイトに変更します。新しいサイズと古いサイズのうち、小さい方のサイズ までのメモリ内容は変更されません。新しいサイズの方が大きい場合、新しく割 り当てられた部分のメモリの値は未定義です。要求されたメモリを割り当てるこ とができなかった場合は NULL が返されますが、 ptr が参照するメモリは有効で 変更されていません。 ptr が NULL である場合、 realloc() 関数は、指定した サイズの malloc() と同じ動きをします。 reallocf() 関数は、要求されたメモリを割り当てることができなかった場合に、 渡されたポインタを解放することを除けば、 realloc() 関数呼び出しと同じで す。これは FreeBSD に固有の API で、 realloc() の従来型のコーディングスタ イルを用いると、ライブラリの内部でメモリリークを引き起こすという問題をな くすために設計されました。 free() 関数は、 ptr で参照される割り当て済みのメモリを今後の割り当てのた めに使用できるようにします。 ptr が NULL である場合、何も実行されません。 |
調整
これらのメモリ割り当てルーチン群の 1 つが初めて呼び出されるときに、この割 り当て実行の動作に影響を与えるさまざまなフラグがセットもしくはリセットさ れます。 /etc/malloc.conf というシンボリックリンクで参照されるファイルの「名称」、 環境変数 MALLOC_OPTIONS の値、グローバル変数 malloc_options が指す文字列 は、この順序で 1 文字毎にフラグとして解釈されます。 ほとんどのフラグは 1 文字で、大文字は動作が設定されたこと、つまりオンに なっていることを表し、小文字は動作が設定されていないこと、つまりオフに なっていることを表します。 |
A
すべての警告 (理解できないフラグが設定されているという警告を除く) を致命的エラーにします。この場合、プロセスは abort(3) を呼び出し ます。 J H R U V X extern char *malloc_options; |
Z
このオプションを設定すると、 ‘‘J’’ オプションと ‘‘R’’ オプション が設定され、要求されたバイト列に 0 が出力されます。これはデバッグ 用のオプションで、パフォーマンスの低下に強い影響を与えます。 < > ‘‘J’’ オプションと ‘‘Z’’ オプションは、テストとデバッグ用です。これらのオ プションを使用しているときに動作が変わるアプリケーションには欠陥がありま す。 使用例 |
キャッシュサイズをシステム全体で小さくし、問題が発生した場合は常にコアダ ンプを取るような設定は、 ln -s ’A<’ /etc/malloc.conf プログラムがこれらの関数の呼出し時に戻り値をチェックしないことをソースで 明示するには、 extern char *malloc_options; malloc_options = "X"; |
環境変数
以下の環境変数は、メモリ割り当て関数の実行に影響を与えます。 |
MALLOC_OPTIONS
環境変数 MALLOC_OPTIONS を設定すると、この環境変数に含ま れる文字は、メモリ割り当て関数群のフラグとして解釈されま す。 戻り値 |
malloc() 関数と calloc() 関数は、成功した場合は割り当てられたメモリへのポ インタを返し、それ以外の場合は NULL ポインタを返し errno を ENOMEM に設定 します。 realloc() 関数と reallocf() 関数は、成功した場合はもしかしたら ptr と同一 の、割り当てられたメモリへのポインタを返します。それ以外の場合は NULL ポ インタを返します。その場合でも ptr によって参照されるメモリは利用可能でそ のまま残ります。メモリの割り当てに失敗した場合は、 errno を ENOMEM に設定 します。 free() 関数は値を返しません。 |
MALLOC の問題のデバッグ
この実装は、割り当てられていない限り解放されているページはアクセスされ ず、再利用のためにカーネルに積極的に返されるという点が、他 (のシステム) のメモリ割り当ての実装と大きく異なります。 ほとんど (のシステム) のメモリ割り当ての実装では、リンクドリストを 含んだデータ構造が、解放されているメモリのかたまりの中に保存され、 解放されているすべてのメモリを互いに結合するために使用されます。解 放リストを行き来するたびに、未使用の、ページアウトされているであろ うページが、プライマリメモリに入るためにページフォルトを起こすた め、これは最適とは言えません。ページングを行うシステムでは、 1 つの プロセスによって生じるページフォルトの数が 5 倍に増加する結果となる ことがあります。 このアーキテクチャには、これまでは検出されなかったインタフェースの細々と した違反が、実際に検出されるようになるという副作用があります。このため、 ずっと問題なく動いていたプログラムが、この割り当ての実装とリンクしたとた んに問題が続出することがあります。 最初にするべきこと、そしてもっとも重要なことは ‘‘A’’ オプションを設定する ことです。このオプションを設定すると、できるだけ処理を継続しようとする通 常の方針をとるかわりに、問題が発生したときに (可能であれば) コアダンプを 強制的に取ります。 デバッガのサポートのために、適切なオプションとシンボルでプログラムを再コ ンパイルするのがおそらく賢明です。 プログラムが、通常とは異なる結果を出したり、コアダンプしたり、次のセク ションで挙げるようなメッセージを出さずに違った動作をし始めるような場合 は、プログラムが 0 のバイトで満たされている記憶領域に依存している場合だと 思われます。 ‘‘Z’’ オプションを設定して実行してみてください。状況が好転し た場合は、この診断が正しかったことになります。これでもプログラムがおかし な動作をするようなら、割り当てられた領域以外のメモリ、大抵は割り当てられ た領域の前方ではなく後方にアクセスするという問題だと思われます。 あるいは、症状が容易に再現しない場合は、 ‘‘J’’ オプションを設定すると問題 を起こす助けになるかもしれません。 本当に難しい状況では、カーネルで ‘‘U’’ オプションがサポートされている場合 はそれを設定すると、これらの関数のすべての呼出しの詳細なトレースが作成さ れます。 あいにく、この実装では、検出された問題に関する詳細は提供されません。その ような情報を保存することで、パフォーマンスが悪影響を受けるためです。パ フォーマンスと引き換えにいっそうの健全さのチェックと詳細な診断を行い、問 題の検出と位置の特定に焦点を当てた数多くのメモリ割り当ての実装が、イン ターネットで利用可能です。 |
診断メッセージ
malloc(), calloc(), realloc(), free() がエラーや警告を検出すると、メッ セージがファイル記述子 STDERR_FILENO に出力されます。エラーの場合、プロセ スはコアダンプします。 ‘‘A’’ オプションを設定すると、すべての警告はエラー として扱われます。 以下では、出力される可能性があるエラーメッセージとその意味について簡単に 説明します。 (ES): mumble mumble mumble ‘‘EXTRA_SANITY’’ が定義された状態でメモリ割り 当て関数がコンパイルされており、詳細なエラーチェック中にエラーが検出され ました。詳細については、ソースコードを参照してください。 mmap(2) failed, check limits システムが危険な過負荷な状態であるか、プロ セスの制限が正しく指定されていないと思われます。 freelist is destroyed 内部の解放リストが壊れています。 out of memory ‘‘X’’ オプションが指定されていて、かつ、メモリの割り当てに 失敗しました。 以下では、出力される可能性がある警告メッセージとその意味について簡単に説 明します。 chunk/page is already free すでに解放されているメモリを free() で解放し ようとしました。 junk pointer, ... メモリ割り当て関数に与えられたポインタが、認識されてい るメモリ境界の外側を指しています。 malloc() has never been called メモリが割り振られていないにも関わらず、 解放しようとしたり、再割り当てしようとしました。 modified (chunk-/page-) pointer free() か realloc() に渡されたポインタが 書き換えられています。 pointer to wrong page realloc(), free() もしくは reallocf() が解放しよう としているポインタが、正しいページを参照していません。 recursive call メモリ割り当て関数を再帰的に呼び出そうとしました。これは 許可されていません。特にシグナルハンドラでは、メモリの割り当てをするべき ではありません。 unknown char in MALLOC_OPTIONS 不明なオプションが指定されました。 ‘‘A’’ オプションを設定していても、この警告は単なる警告として扱われます。 |
関連項目
brk(2), mmap(2), alloca(3), getpagesize(3), memory(3) /usr/share/doc/papers/malloc.ascii.gz |
規格
malloc(), calloc(), realloc(), free() 関数は ISO/IEC 9899:1990 (‘‘ISO C89’’) に適合しています。 |
歴史
現在のメモリ割り当ての実装は、個別のゲルマニウムトランジスタで作成され た、 20 ビットバイナリコンピュータに取り付けられたドラムのファイルシステ ムとしてスタートしました。それ以降は、二次保存域ではなく、一次保存域を操 作するようになりました。この新しい形態と機能は FreeBSD 2.2 ではじめて登場 しました。 reallocf(3) 関数は FreeBSD 3.0 ではじめて登場しました。 |
作者
Poul-Henning Kamp 〈phk@FreeBSD.org〉 |
バグ
問題が発生した場合に出力されるメッセージは、実際の値についての詳細を提供 しません。 0 バイトを割り当てるように要求された場合に NULL ポインタを返すことは、愚 かな問いかけに対する愚かな反応であると言えます。 FreeBSD 10.0 August 27, 1996 FreeBSD 10.0 |