.\" Copyright (c) 1980, 1991, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" the American National Standards Committee X3, on Information .\" Processing Systems. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. All advertising materials mentioning features or use of this software .\" must display the following acknowledgement: .\" This product includes software developed by the University of .\" California, Berkeley and its contributors. .\" 4. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)malloc.3 8.1 (Berkeley) 6/4/93 .\" %Id: malloc.3,v 1.17 1998/09/16 04:07:31 imp Exp % .\" .\" $FreeBSD$ .Dd August 27, 1996 .Dt MALLOC 3 .Os FreeBSD 2 .Sh 名称 .Nm malloc, calloc, realloc, free, reallocf .Nd 汎用のメモリ割り当てのための関数群 .Sh 書式 .Fd #include .Ft void * .Fn malloc "size_t size" .Ft void * .Fn calloc "size_t number" "size_t size" .Ft void * .Fn realloc "void *ptr" "size_t size" .Ft void * .Fn reallocf "void *ptr" "size_t size" .Ft void .Fn free "void *ptr" .Ft char * .Va malloc_options; .Sh 解説 .Fn malloc 関数は、 .Fa size バイトのメモリを割り当てます。 割り当てられた空間は (可能なポインタ強制の後で) あらゆるタイプのオブジェクトが保存できるように適切に調整されます。 その空間の長さが少なくとも .Em pagesize バイトである場合 ( .Xr getpagesize 3 参照 )、返されるメモリはページ境界が調整されていることでしょう。 .Fn malloc に失敗すると、 NULL ポインタが返されます。 .Pp .Fn calloc 関数は、 .Fa number 個の、長さが .Fa size であるオブジェクトに空間を割り当てます。 この関数を呼び出した結果は、割り当てられたメモリがナルに 初期化されていることを除けば、 引数 .Dq "number * size" で .Fn malloc を呼び出した結果と同じです。 .Pp .Fn realloc 関数は、 .Fa ptr で参照される、以前に割り当てられたメモリのサイズを .Fa size バイトに変更します。 メモリの内容は、新しいサイズと古いサイズのうち 小さい方のサイズまでは変化しません。 新しいサイズの方が大きい場合、 新しく割り当てられた部分のメモリの値は未定義です。 要求されたメモリを割り当てることができなかった場合は NULL が返されますが、 .Fa ptr が参照するメモリは有効で変化しません。 .Fa ptr が NULL である場合、 .Fn realloc 関数は、指定したサイズの .Fn malloc と同じ動きをします。 .Pp .Fn reallocf 関数は、要求されたメモリを割り当てることができなかった場合に、 渡されたポインタを解放することを除けば、 .Fn realloc 関数呼び出しと同じです。 これは FreeBSD に固有の API で、 .Fn realloc の従来型のコーディングスタイルを用いると、 ライブラリの内部でメモリリークを引き起こすという 問題をなくすために設計されました。 .Pp .Fn free 関数は、 .Fa ptr で参照される割り当て済みのメモリを 今後の割り当てのために使用できるようにします。 .Fa ptr が NULL である場合、何も実行されません。 .Pp .Sh 調整 これらのメモリ割り当てルーチン群の 1 つが初めて呼び出されるときに、 この割り当て実行の動作に影響を与える さまざまなフラグがセットもしくはリセットされます。 .Pp .Pa /etc/malloc.conf というシンボリックリンクで参照されるファイルの「名称」、 環境変数 .Ev MALLOC_OPTIONS の値、 グローバル変数 .Va malloc_options が指す文字列は、 この順序で 1 文字毎にフラグとして解釈されます。 .Pp ほとんどのフラグは 1 文字で、 大文字は動作が設定されたこと、つまりオンになっていることを表し、 小文字は動作が設定されていないこと、つまりオフになっていることを表します。 .Bl -tag -width indent .It A すべての警告 ( 理解できないフラグが設定されているという警告を除く ) 、 およびメモリ割り当ての失敗を致命的エラーにします。 この場合、プロセスは .Fn abort 3 が呼び出します。 .It J .Fn malloc , .Fn realloc , .Fn reallocf に割り当てられる新規のメモリ、同様に .Fn free , .Fn realloc , .Fn reallocf で返されるメモリの各バイトを 0xd0 に初期化します。 このオプションは .Dq R オプションもセットします。 これはデバッグ用のオプションで、パフォーマンスの低下に強い影響を与えます。 .It H 割り当て関数で使用されないページに関するヒントをカーネルに与えます。 システムが過度にページングを行なっている場合はパフォーマンスが向上します。 このオプションは、デフォルトでオフになっています。 .It R 最初の割り当てが十分に大きい場合であっても、 .Fn realloc 関数と .Fn reallocf 関数が常にメモリの再割り当てをするようになります。 メモリを圧縮する場合の大きな助けとなります。 .Pp .It U すべてのオペレーションで、 .Xr ktrace 1 のための .Dq utrace エントリを生成します。 このオプションの詳細については、ソースを参照してください。 .It V ゼロバイトを割り当てようとしたときに、 有効なポインタの代わりに NULL ポインタが返されるようになります。 ( デフォルトの動作では、最小の割り当てを行なってそのポインタを返します。 ) このオプションは System V との互換性のために提供されています。 このオプションは .Dq X オプションと適合しません。 .It X 割り当て関数でエラーを返す代わりに、 診断メッセージを stderr に 表示し、 ( .Xr abort 3 を使って ) プログラムを core に落します。 このオプションは、コンパイル時に、 ソースコードに以下を組み込むようにして設定するべきです。 .Bd -literal -offset indent extern char *malloc_options; malloc_options = "X"; .Ed .Pp .It Z このオプションを設定すると、 .Dq J オプションと .Dq R オプションが 設定され、要求されたバイト列にゼロが出力されます。 これはデバッグ用のオプションで、パフォーマンスの低下に強い影響を与えます。 .It < キャッシュサイズ 2 分の 1 にします。 デフォルトのキャッシュサイズは 16 ページです。 このオプションは複数回指定できます。 .It > キャッシュサイズを 2 倍にします。 デフォルトのキャッシュサイズは 16 ページです。 このオプションは複数回指定できます。 .El .Pp .Dq J オプションと .Dq Z オプションは、テストとデバッグ用です。 これらのオプションを使用しているときに 動作が変わるアプリケーションには欠陥があります。 .Sh 使用例 キャッシュサイズをシステム全体で小さくし、 問題が発生した場合は常にコアダンプを取るような設定は、 .Pp .Bd -literal -offset indent ln -s 'A<' /etc/malloc.conf .Ed .Pp プログラムがこれらの関数の呼出し時に戻り値をチェックしないことを ソースで明示するには、 .Bd -literal -offset indent extern char *malloc_options; malloc_options = "X"; .Ed .Sh 環境変数 以下の環境変数は、メモリ割り当て関数の実行に影響を与えます。 .Bl -tag -width MMM .It Ev MALLOC_OPTIONS 環境変数 .Ev MALLOC_OPTIONS を設定すると、この環境変数に含まれる文字は、 メモリ割り当て関数群のフラグとして解釈されます。 .Sh 戻り値 .Fn malloc 関数と .Fn calloc 関数は、成功した場合は割り当てられたメモリのポインタを返し、 それ以外の場合は NULL ポインタを返します。 .Pp .Fn realloc 関数と .Fn reallocf 関数は、成功した場合は .Fa ptr と同一の、割り当てられたメモリのポインタを戻します。 それ以外の場合は NULL ポインタを返します。 その場合でも .Fa ptr によって参照されるメモリは利用可能でそのまま残ります。 .Pp .Fn free 関数は値を返しません。 .Pp .Sh MALLOC の問題のデバッグ この実装は、解放されているページには、割り当てられていない限り アクセスされず、再利用のためにカーネルに積極的に返されるという点が、 他 ( のシステム ) のメモリ割り当ての実装と大きく異なります。 .Bd -filled -offset indent ほとんど ( のシステム ) のメモリ割り当ての実装では、 リンクドリストを含んだデータ構造が、 解放されているメモリのかたまりの中に保存され、 解放されているすべてのメモリを互いに結合するために使用されます。 解放リストが横切るたびに、 未使用のはずの、ページアウトされているようなページが、 プライマリメモリに入るためにページフォルトを起こすため、 これは最適とは言えません。 ページングを行なうシステムでは、 一つのプロセスによって生じるページフォルトの数が 5 倍に増加する結果となることがあります。 .Pp このアーキテクチャには、これまでは検出されなかった、インタフェースの 細々とした違反が実際に検出されるようになるという副作用があります。 このため、ずっと問題なく動いていたプログラムが、この割り当ての実装と リンクしたとたんに問題が続出することがあります。 .Pp 最初にするべきこと、そしてもっとも重要なことは .Dq A オプションを設定することです。 このオプションを設定すると、 できるだけ処理を継続しようとする通常の方針をとるかわりに 問題が発生したときに (可能であれば) コアダンプを強制的に取ります。 .Pp デバッガのサポートのために、 適切なオプションとシンボルでプログラムを再コンパイルするのが おそらく賢明です。 .Pp プログラムが、通常とは異なる結果を出したり、コアダンプしたり、 次のセクションで挙げるようなメッセージを出さずに 違ったふるまいをし始めるような場合は、 プログラムがナルバイトで満たされている記憶領域に依存している場合だと 思われます。 .Dq Z オプションを設定して実行してみてください。 状況が好転した場合は、この診断が正しかったことになります。 これでもプログラムがおかしなふるまいをするようなら、 割り当てられた領域以外のメモリ、 大抵は割り当てられた領域の前方ではなく後方にアクセスするという問題だと 思われます。 .Pp あるいは、症状が容易に再現しない場合は、 .Dq J オプションを設定すると問題を起こす助けになるかもしれません。 .Pp 本当に難しい状況では、カーネルで .Dq U オプションがサポートされている場合はそれを設定すると、 これらの関数のすべての呼出しの詳細なトレースが作成されます。 .Pp あいにく、この実装では、検出された問題に関する詳細は提供されません。 そのような情報を保存することで、パフォーマンスが悪影響を受けるためです。 パフォーマンスと引き換えにいっそうの健全さのチェックと詳細な診断を行ない、 問題の検出と位置の特定に焦点を当てた、 利用可能なメモリ割り当ての実装がインターネットには数多くあります。 .Sh 診断メッセージ .Fn malloc , .Fn calloc , .Fn realloc , .Fn free がエラーや警告を検出すると、 メッセージがファイル記述子 STDERR_FILENOに出力されます。 エラーはコアダンプとなります。 .Dq A オプションを設定すると、すべての 警告はエラーとして扱われます。 .Pp 以下では、出力される可能性があるエラーメッセージとその意味について 簡単に説明します。 .Bl -tag -width indent .It "(ES): mumble mumble mumble .Dq EXTRA_SANITY が定義された状態でメモリ割り当て関数がコンパイルされており、 詳細なエラーチェック中にエラーが検出されました。 詳細については、ソースコードを参照してください。 .It "allocation failed .Dq A オプションを指定している場合は、メモリ割り当て関数が失敗すると 致命的なエラーとなります。 .It "mmap(2) failed, check limits システムが危険な過負荷な状態であるか、プロセスの制限が正しく 指定されていないと思われます。 .It "freelist is destroyed 内部の解放リストが壊れています。 .El .Pp .Bl -tag -width indent 以下では、出力される可能性がある警告メッセージとその意味について 簡単に説明します。 .It "chunk/page is already free すでに解放されているメモリを .Fn free で解放しようとしました。 .It "junk pointer ... メモリ割り当て関数に与えられたポインタが、 認識されているメモリ境界の外側を指しています。 .It "malloc() has never been called メモリが割り振られていないにも関わらず、解放しようとしたり、 再割り当てしようとしました。 .It "modified (chunk-/page-) pointer .Fn free か .Fn realloc に渡されたポインタが書き換えられています。 .It "pointer to wrong page .Fn malloc か .Fn calloc が解放 (?) しようとしているポインタが、 正しいページを参照していません。 .It "recursive call メモリ割り当て関数を再帰的に呼び出そうとしました。 これは許可されていません。 特にシグナルハンドラでは、メモリの割り当てをするべきではありません。 .It "out of memory .Dq X オプションが指定されていて、かつ、メモリの割り割り当てに失敗しました。 .It "unknown char in MALLOC_OPTIONS 不明なオプションが指定されました。 .Dq A オプションを設定していても、この警告は単なる警告として扱われます。 .Sh 関連項目 .Xr brk 2 , .Xr alloca 3 , .Xr getpagesize 3 , .Xr memory 3 .Pa /usr/share/doc/papers/malloc.ascii.gz .Sh 規格 .Fn malloc , .Fn calloc , .Fn realloc , .Fn free 関数は .St -ansiC に準拠しています。 .Sh バグ 問題が発生した場合に出力されるメッセージは、 実際の値についての詳細を提供しません。 .Pp ゼロバイトを割り当てるように要求された場合に ヌルポインタを返すことは、 愚かな問いかけに対する愚かな反応であると言えます。 .Pp この実装の作者は、Poul-Henning Kamp です。 問題が発生した場合は、彼 .Li まで報告してください。 .Sh 歴史 現在のメモリ割り当ての実装は、 個々のゲルマニウムトランジスタで作成された、 20 ビットバイナリコンピュータに取り付けられたドラムの ファイルシステムとしてスタートしました。 それ以降は、二次保存域ではなく、一次保存域を操作するようになりました。 この新しい形態と機能は .Fx 2.2 で最初に現れました。