CLASSICISTRANIERI HOME PAGE - YOUTUBE CHANNEL
SITEMAP
Audiobooks by Valerio Di Stefano: Single Download - Complete Download [TAR] [WIM] [ZIP] [RAR] - Alphabetical Download  [TAR] [WIM] [ZIP] [RAR] - Download Instructions

Make a donation: IBAN: IT36M0708677020000000008016 - BIC/SWIFT:  ICRAITRRU60 - VALERIO DI STEFANO or
Privacy Policy Cookie Policy Terms and Conditions
Malloc - Wikipedia

Malloc

出典: フリー百科事典『ウィキペディア(Wikipedia)』

この項目の本来の表記は「malloc」です。MediaWikiの技術的制限から先頭の小文字が大文字になっています。

mallocC言語の標準ライブラリで提供される動的メモリアロケーションを行うサブルーチン(関数)である。

目次

[編集] 原理

C言語は通常メモリを「静的メモリアロケーション」か「自動メモリアロケーション」で管理する。静的変数は主記憶上にプログラムが存在する期間中ずっと確保されている。自動変数(局所変数)はコールスタック上に確保され、対応するサブルーチンが実行中の間だけ存在する。しかし、いずれの方法も限界があり、確保できるメモリ量(変数のサイズ)はコンパイル時に決められてしまう。必要なサイズが実行時でないと判明しない場合、例えばディスク上のファイルから任意のサイズのデータを読み込むような場合、固定サイズのデータオブジェクトだけでは不十分である。

確保されたメモリの生存期間(使用可能期間)も問題となる。静的でも自動的でも確保されたメモリの生存期間はあらゆる状況に対応できるものではない。スタック上のデータは複数の関数コールをまたいで持続できないし、静的データは必要かどうかに関わらずプログラムが動作中ずっとメモリ領域を確保し続ける。多くの場合、確保したメモリの生存期間をプログラマが自由にできる必要がある。

これらの制限は動的メモリアロケーションを使用することで解決する。メモリの管理は明示的に行う必要が出てくるが、柔軟性が向上する。特に「ヒープ領域」はこのために用意されたメモリ領域である。C言語では、malloc関数を使ってヒープ領域からメモリブロックを確保する。プログラムはmallocのリターン値であるポインタを使って、そのメモリブロックにアクセスする。メモリブロックが不要になったら、そのポインタをfreeに渡して解放し、他の用途に再利用できるようにする。

[編集] C言語での動的メモリアロケーション

mallocは C 言語におけるヒープ領域からのメモリ確保に使われる基本関数である。そのプロトタイプは以下のようになる。

void *malloc(size_t size)

ここで、size バイトのメモリが確保される。確保が成功するとそのメモリブロックへのポインタが返される。

mallocが返すのは void 型のポインタ(void *)であり、そのポインタが指す領域のデータ型が不明であることを示している。このポインタは一般に型変換されて必要なデータ型へのポインタとされる。しかし最近ではmallocのリターン値を型変換しないことが推奨されている。本来、mallocchar * を返していて、これは型変換が必須だった。しかし、void * は型変換が必須ではないため、あいまいさが生じる。[1]

mallocで確保されたメモリは持続性がある。プログラム終了時か明示的にプログラマが解放しない限り存在し続ける。解放はfree関数で行われる。そのプロトタイプは次のようになる。

void free(void *pointer)

ここで、pointer の指すメモリブロックが解放される。

[編集] 使用例

スタック上に10個の整数の配列を作成する一般的な方式は次の通りである:

int array[10];

同様の配列を動的に確保するには、以下のようなコードを使うことが出来る。

#include <stdlib.h>

/* 10個のintの配列のためのメモリを確保 */
int *ptr = malloc(sizeof (int) * 10);
if (ptr == NULL)
   exit(EXIT_FAILURE); /* メモリを確保できなかったので、exit */

/* 確保成功 */

[編集] 関連する関数

mallocはメモリブロックを確保して返すが、その領域は初期化されていない。必要に応じてメモリは個別に初期化する。例えば、memset関数で初期化したり、個別の代入文で初期化する。他にもcalloc関数を使って、メモリ確保と初期化を行うこともできる。そのプロトタイプは以下のようになる。

void *calloc(size_t nelements, size_t bytes)

bytesのサイズのメモリ領域をnelements個格納できるメモリ領域を確保する。確保された領域はゼロで初期化される。

メモリブロックを大きくしたり小さくしたりできれば便利である。これはmallocfreeを組み合わせて、新たなメモリブロックを確保して内容を前のメモリブロックからコピーし、前のメモリブロックを解放することで実現できる。しかし、この方法は回りくどい。代わりにrealloc関数を使うことが出来る。そのプロトタイプは以下の通りである。

void *realloc(void *pointer, size_t bytes)

reallocは指定されたサイズのメモリ領域へのポインタを返す。新しいサイズが前のサイズより大きければブロックは大きくされ、逆ならば小さくされる。

vallocmallocとほとんど同じだが、メモリ確保がページ境界になる点が異なる。vallocで確保された領域へのポインタをreallocに渡すことはできない。[1]

[編集] 一般的なエラー

mallocや関連するC言語の関数の使用はバグの発生源になりやすい。

[編集] 確保エラー

mallocは必ず成功するとは限らない。利用可能な空きメモリ領域がないとき、プログラムが限界値を超えてメモリを使用しようとしたときなど、mallocNULLポインタを返す。環境によって、このような状況の起きる可能性は異なる。多くのプログラムはmallocが失敗することを考慮していない。そのようなプログラムでmallocNULLポインタを返してきたとき、プログラムはNULLに相当するアドレスにアクセスしてクラッシュするだろう。これは昔から設計上のミスとされているが、未だにそのようなプログラムが多い[2]。というのもメモリ確保に失敗するという状況は非常に珍しく、発生した場合には終了する以外にプログラミング上できることがない[3]からでもある。確保失敗をチェックすることはライブラリでは特に重要である。ライブラリはメモリ量が限られた状況でも使用される可能性がある。ライブラリ内でメモリ確保に失敗した場合、呼び出したアプリケーション側にエラーを通知して、アプリケーションプログラムに判断を委ねるのがよいとされる。

[編集] メモリリーク

mallocで確保したメモリブロックを使用しなくなってもfreeで解放せず、次々と新たなメモリブロックを確保していると空きメモリが少なくなってくる。これをメモリリークと呼ぶ。メモリリークによるメモリ消費が無視できない量に達するとページ置換アルゴリズムによってページアウトが発生し、システム性能が低下する。さらに仮想記憶の容量限界に達すると、システム内の他の全プロセスでメモリ確保が失敗してシステムがストールする。メモリリーク自体は特に、重要な障害に直結する訳ではないと考えられているため、残念ながら商用プログラムにも相当程度に多い。なお、連続稼動で「酷使」されるサーバプログラムの場合は、メモリリークは死活問題と見なされる。

[編集] 使用後の解放

ポインタがfreeに渡された後でその領域への参照を行っても、その内容は未定義であり利用できない。しかし、ポインタ自体が残っていると使ってしまうことがある。次のコードはその例である。

 int *ptr = malloc(sizeof *ptr);
 free(ptr);
 *ptr = 0; /* 何が起きるかわからない! */

このようなコードは予測不能の振る舞いをする。メモリが解放された後でシステムがその領域を他の用途に転用しているかもしれない。従って解放済みメモリ領域へのポインタを使った書き込みはプログラム内の別のデータを不正に書き換えてしまう。どういうデータを書き換えたかによって、その後のプログラムの動作は単なるデータ破壊で済むかもしれないし、クラッシュするかもしれない。特に破壊的なバグとしては、同じポインタを2回freeに渡してしまうことで、これを「二重解放; double free」と呼ぶ。これを防ぐため、解放した後でポインタ変数にNULLを格納することがある。というのもfree(NULL)は何もしないのである。

[編集] 実装

メモリ管理の実装はオペレーティングシステム(OS)と(ハードウェア)アーキテクチャに大きく依存する。OSによってはmallocのためのアロケータを提供しているし、データ領域の制御関数を提供している場合もある。

同じ動的メモリアロケータでmallocだけでなくC++operator new も実装していることが多い。そこでこれを malloc ではなく「アロケータ」と呼ぶ。

[編集] ヒープ方式

IA-32アーキテクチャでのアロケータの実装には一般にヒープまたはデータセグメントが使用されている(セグメント方式)。アロケータは確保要求を満たすためにヒープを宣言し拡張するのが一般的である。

ヒープ方式はフラグメンテーションという問題がある。どのようなメモリ確保方式でもヒープではフラグメントが発生する。つまり、ヒープ上に飛び飛びに使用中領域と未使用領域が存在することになる。優秀なアロケータはヒープを拡張する前に未使用領域を再利用しようとするだろう。しかし性能問題があるため、リアルタイムシステムでは代わりに「メモリプール」という方式を使う必要がある(特定サイズのメモリブロックのプールを予め用意しておく方式)。

この方式の主な問題はヒープが2つの属性(ヒープ領域の先頭位置とサイズ)しか持っていないことに発している。ヒープは領域全体を満たすメモリを必要とし、その先頭位置は変更できない。従って大きな未使用領域があっても、それは使われることがない。また、あるヒープの直後に別のセグメントがあると、ヒープを拡張することもできない。このため何らかのメモリ量が無駄にされる。

[編集] glibc アロケータ

GNU Cライブラリ(glibc)はLinuxなどのbrkmmapを使用している。brkシステムコールはヒープのサイズを拡張したり縮小したりできる。一方、mmapシステムコールは非常に大きな領域を確保するときに使われる。ヒープには他と同様の問題があるが、mmapで大きな領域の拡張の問題が回避できる可能性がある。

mmapにも問題はある。mmapではページを割り当てて新たなセグメントを作成する。つまり、確保された各セグメントにページが割り当てられている。1バイトしか使っていなくてもページ単位に割り当てが行われ、そのサイズはIA-32では一般に4096バイトである。しかし、大きなページとしては1024倍の4MBのページがあり、これを使っていると、mmap方式は破壊的かもしれない。mmap方式の利点は、セグメントを解放すると対応するメモリが即座に解放される。

[編集] OpenBSD の malloc

OpenBSDmalloc関数の実装はmmapを使用している。ページサイズ以上の要求はmmapで行われ、ページサイズ未満ならmalloc内で管理しているメモリプールから割り当てる。そのメモリプールもmmapで確保したものである。freeを実行すると、munmapを使ってプロセスのアドレス空間からアンマップされて解放される。このシステムはアドレス空間のレイアウトをランダム化することによってセキュリティを高めるための設計でもあり、OpenBSDのmmapが持つギャップページ機能も利用している(mmapで確保した領域が仮想空間上で隣接しないようにする機能)。また、解放後の領域は仮想空間としてマッピングが存在しないため、解放後のアクセスの検出も容易である(普通なら不正なページフォールトが発生してプログラムが終了する)。

[編集] 最大確保サイズ

mallocが確保できるメモリブロックの最大サイズはシステムに依存する。特に物理メモリ量とOSの実装に依存する。理論上の最大値は "size_t" 型(メモリ領域のサイズを表す符号なし整数)である。その最大値は (size_t)-1 か、C99標準の定数 SIZE_MAX である。C言語標準は一回の確保で保証される最小値を提示している(C90 では 0x7FFF、C99 では 0xFFFF)。

[編集] 脚注

  1. stdlib.hをインクルードし忘れた場合、コンパイラはmallocがint型であるとみなす。これをキャストしているとインクルードし忘れたことに気づかないが、キャストしていないとコンパイル時にintをポインタ型変数に代入しようとしているとして何らかのメッセージが表示される
    C FAQ 日本語訳 7.6, C FAQ 日本語訳 7.7
    http://faq.cprogramming.com/cgi-bin/smartfaq.cgi?id=1043284351&answer=1047673478
  2. 特にquick-hack的なコードの場合。行儀の良いまたは良くあるべきソース、例えばアプリケーション製品等では、少ない
  3. これも、前述と同様に、コードの異常系すなわち例外処理はアプリケーション製品では重要な要請である。

[編集] 関連項目

[編集] 外部リンク

Static Wikipedia 2008 (no images)

aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - bcl - be - be_x_old - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - co - cr - crh - cs - csb - cu - cv - cy - da - de - diq - dsb - dv - dz - ee - el - eml - en - eo - es - et - eu - ext - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gan - gd - gl - glk - gn - got - gu - gv - ha - hak - haw - he - hi - hif - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kaa - kab - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mdf - mg - mh - mi - mk - ml - mn - mo - mr - mt - mus - my - myv - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - quality - rm - rmy - rn - ro - roa_rup - roa_tara - ru - rw - sa - sah - sc - scn - sco - sd - se - sg - sh - si - simple - sk - sl - sm - sn - so - sr - srn - ss - st - stq - su - sv - sw - szl - ta - te - tet - tg - th - ti - tk - tl - tlh - tn - to - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu -

Static Wikipedia 2007 (no images)

aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - bcl - be - be_x_old - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - co - cr - crh - cs - csb - cu - cv - cy - da - de - diq - dsb - dv - dz - ee - el - eml - en - eo - es - et - eu - ext - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gan - gd - gl - glk - gn - got - gu - gv - ha - hak - haw - he - hi - hif - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kaa - kab - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mdf - mg - mh - mi - mk - ml - mn - mo - mr - mt - mus - my - myv - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - quality - rm - rmy - rn - ro - roa_rup - roa_tara - ru - rw - sa - sah - sc - scn - sco - sd - se - sg - sh - si - simple - sk - sl - sm - sn - so - sr - srn - ss - st - stq - su - sv - sw - szl - ta - te - tet - tg - th - ti - tk - tl - tlh - tn - to - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu -

Static Wikipedia 2006 (no images)

aa - ab - af - ak - als - am - an - ang - ar - arc - as - ast - av - ay - az - ba - bar - bat_smg - bcl - be - be_x_old - bg - bh - bi - bm - bn - bo - bpy - br - bs - bug - bxr - ca - cbk_zam - cdo - ce - ceb - ch - cho - chr - chy - co - cr - crh - cs - csb - cu - cv - cy - da - de - diq - dsb - dv - dz - ee - el - eml - eo - es - et - eu - ext - fa - ff - fi - fiu_vro - fj - fo - fr - frp - fur - fy - ga - gan - gd - gl - glk - gn - got - gu - gv - ha - hak - haw - he - hi - hif - ho - hr - hsb - ht - hu - hy - hz - ia - id - ie - ig - ii - ik - ilo - io - is - it - iu - ja - jbo - jv - ka - kaa - kab - kg - ki - kj - kk - kl - km - kn - ko - kr - ks - ksh - ku - kv - kw - ky - la - lad - lb - lbe - lg - li - lij - lmo - ln - lo - lt - lv - map_bms - mdf - mg - mh - mi - mk - ml - mn - mo - mr - mt - mus - my - myv - mzn - na - nah - nap - nds - nds_nl - ne - new - ng - nl - nn - no - nov - nrm - nv - ny - oc - om - or - os - pa - pag - pam - pap - pdc - pi - pih - pl - pms - ps - pt - qu - quality - rm - rmy - rn - ro - roa_rup - roa_tara - ru - rw - sa - sah - sc - scn - sco - sd - se - sg - sh - si - simple - sk - sl - sm - sn - so - sr - srn - ss - st - stq - su - sv - sw - szl - ta - te - tet - tg - th - ti - tk - tl - tlh - tn - to - tpi - tr - ts - tt - tum - tw - ty - udm - ug - uk - ur - uz - ve - vec - vi - vls - vo - wa - war - wo - wuu - xal - xh - yi - yo - za - zea - zh - zh_classical - zh_min_nan - zh_yue - zu -

Sub-domains

CDRoms - Magnatune - Librivox - Liber Liber - Encyclopaedia Britannica - Project Gutenberg - Wikipedia 2008 - Wikipedia 2007 - Wikipedia 2006 -

Other Domains

https://www.classicistranieri.it - https://www.ebooksgratis.com - https://www.gutenbergaustralia.com - https://www.englishwikipedia.com - https://www.wikipediazim.com - https://www.wikisourcezim.com - https://www.projectgutenberg.net - https://www.projectgutenberg.es - https://www.radioascolto.com - https://www.debitoformtivo.it - https://www.wikipediaforschools.org - https://www.projectgutenbergzim.com