Dennis Ritchieが書いた「失われたmalloc()」は、現代のmallocより優れていた
The lost malloc()
1973年のUnix V4のソースを辿ると、Dennis Ritchieのディレクトリに現代のmalloc()/free()の前身が残っている。だがそのインターフェースは大きく異なり、確保対象のメモリ領域(coremapやswapmap)を明示的に渡し、解放時にはサイズも渡す設計だった。領域ごとにメモリを分割管理できるため、ヒープ破壊の影響を局所化でき、サードパーティコードの割り当て量も簡単に制限できる。筆者はこれを現代のmalloc()よりはるかに優れた設計だと評する。
それらは従来のmalloc()/free()よりも無限倍優れたインターフェースだ。こんなインターフェースを持つライブラリを使うところを想像してほしい。委任した領域全体を捨てるだけで、そのライブラリのメモリ資源をすべて解放できるのだ。
HNでの議論
42- adrian_b
著者はSIMULA 67が「new」をどこから取ったのかを実際には見つけられなかった。1965年11月、C.A.R. Hoareは「Record Handling」という極めて影響力のある論文を発表した。これはALGOL 60の後継言語のための拡張提案だった。SIMULA 67で前身のSIMULA言語に追加された機能のほとんどすべては、Hoareの論文から直接来ている。ただし2つの大きな例外がある。クラス継承と「仮想」プロシージャで、これらはSIMULA 67の創始者(Kristen NygaardとOle-Johan Dahl)によって発明され、オブジェクト指向プログラミングに不可欠なものだ。SIMULA 67のキーワード「class」と「new」はHoareの論文から取られた(Hoareは実際には「class」をCOBOL 60から取っていた。COBOL 60はALGOL 60と比べて非常に異なる用語を使っており、多くの違いの中でもALGOL 60が使う「type」の代わりに「class」を使っていた)。Hoareの論文は多くのプログラミング言語機能を論じており、そのほとんどが新しかった。コンストラクタとデストラクタを伴う構造化型の定義、判別付き共用体(John McCarthyから取られた)、列挙、NULLポインタなど多数を含む。SIMULA 67はHoareが提案した機能の多くを実装した最初の言語の一つだった。提案された機能の一部を実装した他の言語には、IBM PL/I、ALGOL 68、そして数年後の1970年11月にはPascalがある。キーワード「new」はすでにNiklaus Wirthによって初めて使われていたが、WirthのそれはHoareのとは異なる意味だった。それは変数を宣言した […]
- OskarS
> それだけでなく、mfree()は解放するオブジェクトのサイズを受け取る、本来あるべきように。
私はこれがこの業界の歴史における最大の小さな過ちの一つだといつも思っている。これは多かれ少なかれ、メモリアロケータに本来追跡する必要のないこれらのサイズを追跡させることを強制しているということだ。free()を呼ぶ人が割り当てのサイズを知らないというまともなケースは事実上存在しない。だから今ではその管理を「ユーザー空間」とメモリアロケータの内部で二重に行っている。たとえば、mallocを呼ぶケースを考えてみよう:
* 型Tの単一オブジェクトを割り当てる場合、サイズは単に`sizeof(T)`なので、それをfree()に渡せばよい
* オブジェクトの配列を割り当てる場合、サイズは`count * sizeof(T)`であり、`count`が何かを知らないケースは一度も思い浮かばない。静的サイズ(その場合は単なる定数)か、動的に成長する配列なら再割り当てのタイミングを知るために予約領域を追跡する必要がある。少なくとも境界チェックのために必要だ。
* 生のメモリのチャンクの場合も、前の点と同じ理由で、解放時に割り当てた生メモリのサイズを知っていると推測される。サイズ情報なしで生のchar*ポインタを放置するのは、ひどいCの慣行だ。
もし本当に割り当てのサイズを知らないなら(いつそんなことが起きるか想像するのは非常に難しい)、ユーザー側で何らかの方法で追跡することを強制されるべきで、委任するべきではない […]
- veltas
ここで著者にそれほど共感しないのは、'アリーナアロケータ'に熱狂していないし、freeがサイズを受け取らないことを特に気にしていないからだ。インターフェースはまあ良かったと思う。
また、'アリーナアロケータ'(20年ほど前は別の意味だったので、名前がただリブランドされただけだと思う)はそれほど良くない。いくつかのことを簡単にし、時にはパフォーマンスを向上させるが、注意して使わないとより多くのメモリを使い、断片化を引き起こす傾向がある。それが、古いリニアアロケータから徐々に進化して離れた多くの理由の一つであり、また単に複雑さを隠すためのシンプルで柔軟なインターフェースが欲しかったからでもある。
- fjfaase
Linuxのsbrkシステムコールは、オペレーティングシステムからより多くのヒープを取得するために今でも利用可能だ。したがって、メモリは依然としてリニアに割り当てられ、二度と解放されない。おそらく今ではmmapのような関数がこれを変えている。私は非常に限定された標準ライブラリ実装のためにmallocを実装するのにsbrkを使った。
- jdw64
私が大学生だった頃(15年前)、『A Book on C』を通じて初めてCに出会い、Cはシンプルだが本当に多くのことができる言語のように思えた。この言語がどれほど古いか、そして現代の言語ですでに使われている多くの概念がその開発史の中で試されていたことを見ると驚く。今日の現代的な技術だと思っていた概念が、何十年も前、つまり私が生まれる前にすでに試されていたというのは驚きだ。
Bump Allocatorのような方法がすでに試されていたなんて驚きだ。
先輩プログラマーたちはどうやってそんなことができたのだろう?ただただ驚嘆する。