ユーザー定義の malloc 置換

メモリー・サブシステム (malloccallocrealloc freemallopt、および mallinfo サブルーチン) は、 ユーザー独自の設計によるサブシステムに置き換えることができます。

注: C++ で作成された置換メモリー・サブシステムは、C++ ライブラリー libC.alibc.a メモリー・サブシステムを使用するため、サポートされません。

既存のメモリー・サブシステムは、スレッド化アプリケーションと 非スレッド化アプリケーションの両方で働きます。 ユーザー定義のメモリー・サブシステムは、スレッド化プロセスと非スレッド化プロセスの両方で働けるようにスレッド・セーフである必要があります。 スレッド・セーフかどうかを検証する検査はないので、非スレッド・セーフのメモリー・モジュールがスレッド化アプリケーションにロードされた場合は、メモリーやデータが破壊される可能性があります。

ユーザー定義メモリー・サブシステムの 32 ビット・オブジェクトと 64 ビット・オブジェクトは、以下の名前の 32 ビット共有オブジェクトを持つアーカイブに配置する必要があります。mem32.oおよび以下の名前の 64 ビット共有オブジェクトmem64.o.

ユーザー共有オブジェクトは、以下のシンボルをエクスポートする必要があります。
  • __malloc__
  • __free__
  • __realloc__
  • __calloc__
  • __mallinfo__
  • __mallopt__
  • __malloc_init__
  • __malloc_prefork_lock__
  • __malloc_postfork_unlock__
ユーザー共有オブジェクトは、任意で以下のシンボルをエクスポートすることができます。
  • __malloc_start__
  • __posix_memalign__

これらのシンボルが存在しなくても、実行は停止しません。

関数の定義を、以下に示します。
void *__malloc__(size_t):
この関数は、malloc サブルーチンに相当するユーザーの関数です。
void __free__(void *):
この関数は、free サブルーチンに相当するユーザーの関数です。
void *__realloc__(void *, size_t):
この関数は、realloc サブルーチンに相当するユーザーの関数です。
void *__calloc__(size_t, size_t):
この関数は、calloc サブルーチンに相当するユーザーの関数です。
int __mallopt__(int, int):
この関数は、mallopt サブルーチンに相当するユーザーの関数です。
struct mallinfo __mallinfo__():
この関数は、mallinfo サブルーチンに相当するユーザーの関数です。
void __malloc_start__()
この関数は、他のユーザー定義 malloc エントリー・ポイントが呼び出される前に一度呼び出されます。
void __posix_memalign__()
この関数は、posix_memalign サブルーチンに相当するユーザーの関数です。 このシンボルが存在しない場合、実行は停止しませんが、 posix_memalign サブルーチンに対して呼び出しを行うと、予期しない結果が生じます。
以下の関数は、マルチスレッド環境のユーザー定義のメモリー・サブシステムを管理するために、スレッド・サブシステムが使用します。 これらは、アプリケーションまたはユーザー定義モジュール が libpthreads.a とバインドされている場合にのみ呼び出されます。 ユーザー定義サブシステムがスレッド・セーフではなく、 libpthreads.a とバインドされていない場合でも、これらの関数は定義およびエクスポートされる必要があります。 そうしない場合、オブジェクトがロードされません。
void __malloc_init__(void)
pthread 初期化ルーチンによって呼び出される。 この関数は、スレッド化ユーザー・メモリー・サブシステム を初期化するために使用されます。 ほとんどの場合、これには、ある形式のロック・データの作成や初期化などがあります。 ユーザー定義メモリー・サブシステム・モジュールが libpthreads.aでバインドされている場合でも、ユーザー定義メモリー・サブシステムは事前に機能 しなければなりません__malloc_init__()呼び出されます。
void __malloc_prefork_lock__(void)
以下の場合に pthread によって呼び出されます。forkサブルーチンが呼び出されます。 この機能を使用すると、メモリー・サブシステムの状態が既知の状態になってから、fork()そして、次のようになります。fork()が返されました。 ほとんど場合、これには、メモリー・サブシステム・ロックの獲得などがあります。
void __malloc_postfork_unlock__(void)
以下の場合に pthread によって呼び出されます。forkサブルーチンが呼び出されます。 この関数は、メモリー・サブシステムを親および子で使用可能にするために使用されます。forkこれにより、以下によって行われた作業が元に戻されます。__malloc_prefork_lock__ほとんどの場合、これにはメモリー・サブシステム・ロックの解放が含まれます。
関数は、すべて共有モジュールからエクスポートする必要があります。 アーカイブの中にある 32 ビットと 64 ビットのインプリメンテーションに対し、 別個のモジュールが存在していなければなりません。 次に例を示します。
  • mem.exp モジュール:
    __malloc__
    __free__
    __realloc__
    __calloc__
    __mallopt__
    __mallinfo__
    __malloc_init__
    __malloc_prefork_lock__
    __malloc_postfork_unlock__
    __malloc_start__
  • mem_functions32.o モジュール:

    必要な 32 ビット関数のすべてが入っている。

  • mem_functions64.o モジュール:

    必要な 64 ビット関数のすべてが入っている。

以下の例は、共有オブジェクトを作成する場合の例です。 この-lpthreadsパラメーターは、オブジェクトが pthread 関数を使用する場合にのみ必要です。
  • 32 ビット共有オブジェクトの作成:
    ld -b32 -m -o mem32.o mem_functions32.o \
    -bE:mem.exp \
    -bM:SRE -lpthreads -lc
  • 64 ビット共有オブジェクトの作成:
    ld -b64 -m -o mem64.o mem_functions64.o \
    -bE:mem.exp \
    -bM:SRE -lpthreads -lc
  • アーカイブの作成 (共有オブジェクト名は、以下のようにする必要があります。mem32.o32bit オブジェクトの場合mem64.o64bit ・オブジェクトの場合):
     ar -X32_64 -r archive_name mem32.o mem64.o

ユーザー定義のメモリー・サブシステムの使用可能化

ユーザー定義のメモリー・サブシステムは、以下のいずれかを使用して使用可能にできます。
  • MALLOCTYPE 環境変数
  • この_malloc_user_defined_nameユーザーのアプリケーション内のグローバル変数

MALLOCTYPE 環境変数を使用するには、 MALLOCTYPE を次のように設定して、ユーザー定義メモリー・サブシステムを含むアーカイブを指定します。user:archive_nameここで、 archive_name はアプリケーションのlibpathまたは、パスが LIBPATH 環境変数に指定されています。

以下を使用します。_malloc_user_defined_nameグローバル変数の場合、ユーザーのアプリケーションはグローバル変数を以下のように宣言する必要があります。
char *_malloc_user_defined_name="archive_name"

この場合、archive_name は、アプリケーションの libpath か、または LIBPATH 環境変数で指定したパスにある必要があります。

注:
  1. setuid アプリケーションが実行されると、LIBPATH 環境変数は無視されるので、アーカイブはアプリケーションの libpath にある必要があります。
  2. archive_name には、 パス情報を入れることはできません。
  3. MALLOCTYPE 環境変数と MALLOCTYPE_malloc_user_defined_nameグローバル変数を使用して archive_nameを指定すると、 MALLOCTYPE によって指定されたアーカイブが指定変更されます。_malloc_user_defined_name.

32 ビットと 64 ビットに関する考慮事項

アーカイブに 32 ビットと 64 ビットの両方の共有オブジェクトが入っていない場合で、 かつユーザー定義のメモリー・サブシステムが MALLOCTYPE 環境変数 を用いて使用可能になった場合は、32 ビット・アプリケーションからの 64 ビット・プロセス の実行と、64 ビット・アプリケーションからの 32 ビット・プロセスの実行で問題が生じます。 新しいプロセスは、exec サブルーチンを用いて作成される際、 コール側アプリケーションの環境を受け継ぎます。 つまり、MALLOCTYPE 環境変数は継承され、新規プロセスはユーザー定義メモリー・サブシステムのロードを試みます。 このタイプのプログラムに関するアーカイブ・メンバーがなければ、 ロードは失敗し、新しいプロセスは終了します。

スレッドに関する考慮事項

提供されている関数はすべて、マルチスレッド環境で働く必要があります。 モジュールが libpthreads.aとリンクされている場合でも、少なくとも__malloc__()事前に機能 しなければならない__malloc_init__()が呼び出され、pthread が初期化されます。 これが必要なのは、pthread の初期化にはmalloc()次の日付以前__malloc_init__()呼び出されます。

提供されているメモリー関数はすべて、 スレッド化環境と非スレッド化環境の両方で働く必要があります。 この__malloc__()に依存せずに完了まで実行できなければなりません。__malloc_init__()(つまり、__malloc__()最初に想定する必要があります__malloc_init__()はまだ実行 されていません 。) 後__malloc_init__()完了しました。__malloc__()によって行われるあらゆる仕事に頼ることができる__malloc_init__()。これは、pthread 初期化が以下を使用するために必要です。malloc()次の日付以前__malloc_init__()呼び出されます。

不要なスレッド関連ルーチンが呼び出されることを防ぐために、以下の変数が備えられています。
  • この__multi_threaded変数は、ゼロ以外になったときにスレッドが作成されるまでゼロになり、そのプロセスについてはゼロにリセットされません。
  • この__n_pthreads変数は-1pthread が初期化されるまで、次の値に設定されます。1. その時点から、アクティブ・スレッドの数がカウントされます。

例:

指定する場合は、__malloc__()使用pthread_mutex_lock()コードは、以下のようになります。

if (__multi_threaded)
pthread_mutex_lock(mutexptr);

/* ..... work ....... */

if (__multi_threaded)
pthread_mutex_unlock(mutexptr);

この例では以下のようにします。__malloc__()pthread が完全に初期化される前に、pthread 関数を実行することはできません。 2 番目のスレッドが開始するまでロックが行われないので、 単一スレッド・アプリケーションも加速されます。

制限

C++ で書かれたメモリー・サブシステムは、libC.a の初期化の問題と依存関係、 ならびに libc.a メモリー・サブシステムの理由で、サポートされません。

setlocale サブルーチンが使用するため、エラー・メッセージは変換されません。malloc()ロケールを初期化します。 指定する場合は、malloc()失敗した場合、 setlocale サブルーチンは終了できず、アプリケーションはまだPOSIXロケール。 したがって、デフォルトの英語メッセージのみが表示されます。

静的に作成された既存のプログラムは、再コンパイルしないと、ユーザー定義のメモリー・サブシステムを使用できません。

エラー・レポート作成

malloc サブルーチンが最初に呼び出されるときに、MALLOCTYPE 環境変数で指定されたアーカイブの 32 ビットもしくは 64 ビット・オブジェクトがロードされます。 ロードが失敗すると、メッセージが表示され、アプリケーションは終了します。 ロードが成功すると、必要なシンボルがすべて存在しているかどうかの確認が試みられます。 欠落しているシンボルがあると、アプリケーションは終了し、 欠落シンボルのリストが表示されます。