TBOXは、使用して、C言語クロスプラットフォーム開発ライブラリです。
各プラットフォームのためのあなたので、一般的な操作の様々なタイプで使用される開発プロセスを簡素化し、パッケージ化され統一されたインタフェース、開発プロセスでは、上記の些細なインターフェイスの互換性の実用的なアプリケーションの開発ではなく、時間を無駄にもっと注意、およびフル活用します各プラットフォームのユニークな特徴のいくつかは、最適化されています。
このプロジェクトの目的は、簡単なCの開発をより効率的にすることです。
- ソース倉庫:https://github.com/tboox/tbox
- オンラインマニュアル:https://tboox.io/#/zh-cn/
メモリ全体のアーキテクチャ
TBOXメモリ管理モデル、Linuxカーネルのメモリ管理メカニズムを参照し、その基礎の上にいくつかの改善と最適化を行いました。
大容量メモリプール:large_pool
全体のメモリ割り当ての底部は、Linuxベースの配信管理ページに似て大容量メモリ割り当てプールlarge_pool、に基づいているが、異なるであり、しないLinuxの行為(2 ^ N)のようなlarge_pool使用バディアルゴリズムとして*ページは、強度が非常に無駄な、大きすぎるので、あなたは、メモリ2.1メートル、メモリのブロックを割り当てる4メートルの必要性を必要とするのであれば、割り当てられています。
各スペースの多くても1つの少ない廃棄物で割り当てこれにより、最小のサイズに基づいて割り当てられたN *ページ内部large_poolのPAGE_SIZEを使用。
あなたが少ないフルページメモリよりも必要な場合は、必要に応じて、残りのメモリはまた、(例えばsmall_poolなど)上位、上位層に戻されると、あなたは、メモリ使用量が最適化されたように、メモリ空間のこの余分な部分を利用することができます。
そして、実際の需要tb_initに渡されたパラメータに応じて、large_poolは、2つのモードがあります。
- 直接使用するシステムのメモリ割り当てインタフェースは言っていない、これは比較的単純で、メモリのチャンク、および二本鎖メンテナンスが割り当てられます。
- 連続したメモリの大部分の管理を統一し、メモリの割り当てを実現しています。
どちらの方法で特定の使用、アプリケーションの要件に応じて、一般的なアプリケーションでは、唯一の行に1を使用する必要があり、ラインでこの時間tb_initパスtb_null、それは組み込みアプリケーション、メモリ空間の限られた部分を管理する必要がある場合は、この時間あなたは2を使用することができ、指定されたメモリアドレスとサイズを着信tb_init。
ここで、メインメモリルック実施形態のlarge_pool構造2は、(ページサイズは4キロバイトであると仮定します)。
--------------------------------------------------------------------------
| data |
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
| head | 4KB | 16KB | 8KB | 128KB | ... | 32KB | ... | 4KB*N |
--------------------------------------------------------------------------
片があまりできなくなり、上部small_poolにおける超小型分布は、このアプリケーション、large_poolあまりに頻繁ではない割り当てがので、スプリットオフしてきたが、さらに、主に大きなブロックの割り当てに使用large_poolを低減します断片化、次の隣接する空きブロックが自由な時間ですマージ。現在の割り当てのmallocとfreeブロックの場合には十分なスペースがありませんが、それは次の隣接する空きブロックをマージしようとします。
各メモリブロックは、二本鎖メンテナンスが無用の近くにあるので、次のないメモリブロックがちょうどサイズのメモリブロックヘッダフィールドをマージする処理を変更する、ヘッダーを持っていないために、この合併は効率に影響を与えないであろう。
、効率が低すぎるので、スペースやメンテナンス時間リストを保存しますが、各注文が空きメモリを見つけるために、すべての割り当てられたメモリブロックを横断しなければならないが、それは、二本鎖メンテナンスフリーメモリとしてバディアルゴリズム好きではなかったので、この問題を解決するために、内部large_poolブロックの異なるレベルが、予測された遊離または次のようにmalloc関数毎に、予測するプール内の対応するレベルに電流され、隣接するフリー高速キャッシュ場合、特定の等級付けしました。
--------------------------------------
| >0KB : 4KB | > 0*page |
|-----------------------|--------------
| >4KB : 8KB | > 1*page |
|-----------------------|--------------
| >8KB : 12-16KB | > 2*page |
|-----------------------|--------------
| >16KB : 20-32KB | > 4*page |
|-----------------------|--------------
| >32KB : 36-64KB | > 8*page |
|-----------------------|--------------
| >64KB : 68-128KB | > 16*page |
|-----------------------|--------------
| >128KB : 132-256KB | > 32*page |
|-----------------------|--------------
| >256KB : 260-512KB | > 64*page |
|-----------------------|--------------
| >512KB : 516-1024KB | > 128*page |
|-----------------------|--------------
| >1024KB : 1028-...KB | > 256*page |
--------------------------------------
メモリの割り当ては、限り、それはメモリ1メートルを予測することができますように、一般的に十分な大きすぎるブロックではなく、また、単一の予測が追加されます> 1メートルメモリ、のために、スーパーチャンクは時折に対処するために割り当てられ、かつ全体的なプロセスをより分与作るので、団結。
現在のレベルの予測ブロックが存在しない場合は、見つからない場合は、検索する予測ブロックの次のレベルに、メモリプール全体を通じて戻ります。
各ブロックの成功を予測するため、実際の試験中95%より上基本的に、それはほとんどの場合、配分効率はO(1)レベルに維持されます。
小さなメモリプール:small_pool
小さなメモリ割り当てプール
メモリはまたは、1に等しいlarge_poolから直接分配される以上であれば、判断を行くためにどのくらいのメモリニーズのmalloc上位メモリ割り当てへの各呼び出しは、それが1未満である場合には、優先的にsmall_pool、small_poolを介して配布されます小さなメモリキャッシュのために行われ、スペース管理・配信効率を最適化します。
ほとんどの場合、プログラムは、小さなメモリの使用において、そのメモリの割り当ては、転換の多くを行うsmall_pool以来、圧力がlarge_poolを減少するように、断片化の量を減らし、多くの、そしてfixed_poolの内部small_poolによるものです固定サイズのメモリ管理は、外部の破片の存在ではありません。粒径の小さなメモリ自体は、量が非常に小さい内部断片である、小さいです。
small_poolでfixed_pool、SLUBなどのLinuxカーネル、12 small_poolレベルfixed_poolの合計で、各レベルは別々に、固定サイズのメモリブロック、特に次のレベルの管理:
--------------------------------------
| fixed pool: 16B | 1-16B |
|--------------------------------------|
| fixed pool: 32B | 17-32B |
|--------------------------------------|
| fixed pool: 64B | 33-64B |
|--------------------------------------|
| fixed pool: 96B* | 65-96B* |
|--------------------------------------|
| fixed pool: 128B | 97-128B |
|--------------------------------------|
| fixed pool: 192B* | 129-192B* |
|--------------------------------------|
| fixed pool: 256B | 193-256B |
|--------------------------------------|
| fixed pool: 384B* | 257-384B* |
|--------------------------------------|
| fixed pool: 512B | 385-512B |
|--------------------------------------|
| fixed pool: 1024B | 513-1024B |
|--------------------------------------|
| fixed pool: 2048B | 1025-2048B |
|--------------------------------------|
| fixed pool: 3072B* | 2049-3072B* |
--------------------------------------
前記96B、192B、384Bは、3072Bのサイズは、主に小さな内部断片化によってメモリ空間のより効率的な使用を行うことにより、2の整数乗ではありません。
固定ブロックメモリプール:fixed_pool
名前が示すように、それは複数のfixed_poolスロットを順番にLinuxのSLUBに対応する、メモリ割り当てfixed_pool固定サイズを管理するために使用され、各スロットは、Linuxと同様の連続したメモリ空間、メモリ管理ブロック管理部、を担っていますスラブは、各スロットは、三のスロット管理に分け、二本鎖、及び基準Linux管理システムによって維持されます。
- 現在割り当てられたスロット
- 空きスロットのリストの一部
- スロットの完全なリスト
次のように具体的な構造は次のとおりです。
current:
--------------
| |
-------------- |
| slot |<--
|--------------|
||||||||||||||||
|--------------|
| |
|--------------|
| |
|--------------|
||||||||||||||||
|--------------|
||||||||||||||||
|--------------|
| |
--------------
partial:
-------------- -------------- --------------
| slot | <=> | slot | <=> ... <=> | slot |
|--------------| |--------------| |--------------|
|||||||||||||||| | | | |
|--------------| |--------------| |--------------|
| | |||||||||||||||| | |
|--------------| |--------------| |--------------|
| | |||||||||||||||| ||||||||||||||||
|--------------| |--------------| |--------------|
|||||||||||||||| |||||||||||||||| | |
|--------------| |--------------| |--------------|
|||||||||||||||| | | | |
|--------------| |--------------| |--------------|
| | | | ||||||||||||||||
-------------- -------------- --------------
full:
-------------- -------------- --------------
| slot | <=> | slot | <=> ... <=> | slot |
|--------------| |--------------| |--------------|
|||||||||||||||| |||||||||||||||| ||||||||||||||||
|--------------| |--------------| |--------------|
|||||||||||||||| |||||||||||||||| ||||||||||||||||
|--------------| |--------------| |--------------|
|||||||||||||||| |||||||||||||||| ||||||||||||||||
|--------------| |--------------| |--------------|
|||||||||||||||| |||||||||||||||| ||||||||||||||||
|--------------| |--------------| |--------------|
|||||||||||||||| |||||||||||||||| ||||||||||||||||
|--------------| |--------------| |--------------|
|||||||||||||||| |||||||||||||||| ||||||||||||||||
-------------- -------------- --------------
具体的な割り当てアルゴリズム
- アイドルスロットのブロックが現在存在する場合、現在のスロット割当優先順位より
- 現在のスロットが空きブロックされていない場合は、への完全なリストのスロットに入れます
- スロットリストから部分的に自由に、空きスロットの割り当てを選択し、それが現在の割り当て状況に設定されています。
特定のリリースのアルゴリズム
- 完全に無料のリリース後スロットとはスロットが割り当てられていない場合は、全体のスロットの両方が割り当て可能なスロットがあることを確認するために、解放されたが、また、大幅にメモリ使用量を削減するだけでなく、特定の状況を避けるために置きます頻繁にリリース下に割り当てられたスロット。
- スロットのリリースは完全なリストとアイドルの一部になるに属している場合は、リストに移動空きスロットスロットのこの部分を置きます。
それを言及するために追加:
スロットの各割り当てのlarge_pool空間は、残りのスペースは、部分(<1 *ページ)を残ったとき、そう完全に分離することができるデータスロットのこの部分を使用するとカットがより多くのメモリことは、スロットに直接戻すことができますブロック。
例えば:
各時間は、メモリブロック32Bを含む番目のスロット256 fixed_pool成長実際の分布を決定し、使用large_pool 8208Bのサイズのニーズを割り当てで、ページに必要(4キロバイト)整列した場合、実際には、(8192Bのサイズは、内部データサイズ+ 16Bを維持するために必要)取り込み8192+4096: 12288B
領域のサイズ。
12288Bので、実際の分割アップ:しかしlarge_poolは、すべての空間データは、一緒にそのメモリのスロット実際に12288B量を取得するには、トップに戻って、そしてまた、その実際のサイズを知っているサポート(12288-(32B的slot内部维护数据))/32
メモリの383ブロックです。
複数のメモリブロック127のメンテナンスは、large_pool上の内部断片化の完全な使用はまた、メモリの使用率を増加させます。
スロットでfixed_pool
スラブ内のLinuxとの類似が、そのデータ構造は、実際に、スラブと同じではないが、それは、スラブ好きではないように、各アイドル小ためのリストを維持するために使用されるが、ビット・セグメントに、直接情報を維持するためにアイドル状態これはほぼ同じ、その物流の効率化とスラブをより多くのメモリを節約するだけでなく、最適化アルゴリズムによる。
ないメモリブロックが存在しないので、各タイルのアイドル情報を維持するために、各ブロックは、情報のビットが一時的であるスロットのFixed_poolヘッドは、小さな専用の独立したデータである、ブロックがフリーであるか否かを判定する彼らはサイズ、ビット位置の位置を固定され、インデックスが計算により求めることができます。
各放出及び分布は、情報ビットはダブルワードサイズの最後にキャッシュされ、予測するために32の隣接するまで、各キャッシュので、ダブルワード・サイズ、32ビットの合計ので、時間分布を予測しますメモリブロック。したがって、ほとんどの場合、そうsmall_poolシャントlarge_pool、また、ある程度まで、はるかに高いも成功率が予測レートlarge_poolに比べ、98%、資源配分効率はO(1)に維持されている>された予測しますさらに、メモリ割り当ての効率を向上させます。
そして、それは不運であっても、成功を予測していなかった、無料の高速アルゴリズムを見つけるためのスロットトラバーサルの順序は、非常に効率的であり、高度以下で詳細に説明した後、完全に最適化されました。
スロット割当順トラバーサルアルゴリズムの最適化
ここでは、主に内蔵されたGCCの機能をいくつか使用します。
- __builtin_clz:32ビット整数演算先行ゼロ
- __builtin_ctz:整数、32ビット番号0ポスト
- __builtin_clzll:0をリードの数の64ビット整数演算
- __builtin_ctzll:0ポストの64ビット整数の数を数えます
実際には、4類似し、ここで私たちは、あなたがそれ__builtin_clz使用したい理由を説明最初の良いを取りましたか?あなたはすぐに空きブロックの位置を特定することができますので、実際には、32ビットの内部を終了するために、すぐに、アイドル位置のインデックスを見つけます。
そのような情報の32ビット整数のビットセグメントとして:X、アイドルビットインデックス計算、メイン必要に0に相当します。__builtin_clz(~x)
それは、シンプルであるため__builtin_clzこれらの組み込み関数、との異なるプラットフォーム用のgccのコンパイルの高い、最適化されていないその後、GCCコンパイラ行うのですかどのようにすれば、かなり速い計算しますか?
それは問題では、我々は、最適化されたバージョンを達成cが所有することができないため、当然のことながら、ここに達成するために最適化コンパイルし続けることができ、Cを与えることです:
static __tb_inline__ tb_size_t tb_bits_cl0_u32_be_inline(tb_uint32_t x)
{
// check
tb_check_return_val(x, 32);
// done
tb_size_t n = 31;
if (x & 0xffff0000) { n -= 16; x >>= 16; }
if (x & 0xff00) { n -= 8; x >>= 8; }
if (x & 0xf0) { n -= 4; x >>= 4; }
if (x & 0xc) { n -= 2; x >>= 2; }
if (x & 0x2) { n--; }
return n;
}
端的に言えば、それは少しずつよりも、すでに言及していない、非常に効率的であり、列挙トラバーサルは、それが__builtin_clzたびに、判決の数を減らすために、各半分を開くことです。
そして、特定のトラバーサルを見て:
- スタートビットのセグメントアドレスは4/8によってバイト整列
- 4/8ビットセグメントデータバイトのトラバース、トラバース使用してCPUのキャッシュサイズは、最適化のパフォーマンスに、ループの展開を目標としますたびに。
- 決定することによって!(X + 1)、これらのビットフィールドの既に完全急速濾過によって0xFFFFFFFFのさらなるトラバーサル効率を向上させます。
- ビットセグメントは0xFFFFFFFFのない場合、ブロックインデックスは、実際のフリー__builtin_clz(〜X)、及び実際の割り当てによって算出します。
- 32ビットのビットセグメントが満杯割り当てられていない場合、最終的に、次の割り当てのための予測を行うためにキャッシュすることができます。
文字列のメモリプール:string_pool
これについて話しました、TBOXメモリプール管理モデル、基本的に完成についても、ここでは単につまり、次のstring_poolに言及:文字列プール
string_poolために主に上位のアプリケーションのために、頻繁に特定の、および反復モジュールの高い割合のための小さな文字列の使用は、参照カウント+ためstring_pool内部ハッシュテーブル更新により、さらにメモリ使用量を低減すること、string_poolことによって最適化することができます唯一、同じ文字列のコピーを保存します。
例えば、クッキーは、文字列を維持するために使用することができる、文字列は、HTTPヘッダ部分等に維持しました。。
グローバルメモリアロケータを切り替えます
デフォルトのメモリ割り当てTBOXをサポートし、高速メモリの割り当てという、独自のメモリプールアーキテクチャに完全に基づいて、破片の最適化、およびメモリリーク、オーバーフロー検出の様々なサポートしています。
TBOXは今、完全にアロケータアーキテクチャをサポートしているので、あなたは、組み込みのデフォルトメモリ割り当て管理TBOXにしたいが、また別のディストリビューションモデルへの切り替えに柔軟性していない場合は、
単に初期化代理店モデルで異なる段階を通過し、あなたには、例えば、割り当てモードをすばやく切り替えることができます。
デフォルトのメモリアロケータ
デフォルトTBOXのメモリ管理を使用して初期化TBOXデフォルトでは、彼はすべての機能をこぼし、デフォルトのメモリプールのメンテナンス、破片の最適化、メモリリークの検出で有効になります。
tb_init(tb_null, tb_null);
初期ザ・上記と同等です。
tb_init(tb_null, tb_default_allocator(tb_null, 0));
デフォルトのアロケータは、システムのネイティブネイティブのメモリを使用してmallocのシステムへの通常の直接呼び出しますが、メモリ管理およびメモリ・テスト・支持層以上に基づいて、あなたは完全に連続したメモリの一部にホストされているしたい場合は、以下の方法を使用することができます:
tb_init(tb_null, tb_default_allocator((tb_byte_t*)malloc(300 * 1024 * 1024), 300 * 1024 * 1024));
スタティックメモリアロケータ
我々はまた、直接均一な静的バッファのメンテナンスのために使用することができ、すべての機能は、この差tb_default_allocatorとメモリリーク検出、オーバーフローを、有効になっていることを
低いリソースに適した分配比較的軽量、簡単な内部データ構造、小さなフットプリント、分配このようないくつかの組み込み環境のような環境では、より高い資源利用です。
!>しかし、アロケータは破片になりやすいの断片化の最適化をサポートしていません。
tb_init(tb_null, tb_static_allocator((tb_byte_t*)malloc(300 * 1024 * 1024), 300 * 1024 * 1024));
ネイティブメモリアロケータ
任意の内部データ処理およびメンテナンス、システム環境の特性に依存するすべてのないシステムメモリの割り当てのネイティブフル使用は、メモリとメモリプール検出特性は、直接のmallocのような分配システムのインターフェースを通過対応するサポートされていません。
あなたは、内蔵メモリTBOXプールのメンテナンスを使用しない場合、ユーザーは自分のニーズに応じて、あなたはこのディスペンサーを使用することができます。
tb_init(tb_null, tb_native_allocator());
仮想メモリアロケータ
仮想メモリアロケータ、主メモリの一部の超大型ブロックを割り当てるために使用される:v1.6.4バージョン後、TBOXは、分配の新しいタイプを提供します。
通常、内部TBOXデフォルトのメモリアロケータは、メモリブロックの自動スーパーチャンクが仮想メモリプールの割り当てに切り替えることになるため、ユーザーは、それを必要としませんが、仮想メモリの割り当てにスイッチを強制したい場合は、以下により、間のスイッチへの道:
tb_init(tb_null, tb_virtual_allocator());
カスタムメモリアロケータ
あなたはこれらのディスペンサーは十分でないと感じた場合、あなたは、カスタマイズされた方法も非常に簡単で、使用にTBOXを聞かせて、あなた自身のメモリアロケータをカスタマイズすることができ、ここで取るtb_native_allocator
例として実装コードを:
static tb_pointer_t tb_native_allocator_malloc(tb_allocator_ref_t allocator, tb_size_t size __tb_debug_decl__)
{
// trace
tb_trace_d("malloc(%lu) at %s(): %lu, %s", size, func_, line_, file_);
// malloc it
return malloc(size);
}
static tb_pointer_t tb_native_allocator_ralloc(tb_allocator_ref_t allocator, tb_pointer_t data, tb_size_t size __tb_debug_decl__)
{
// trace
tb_trace_d("realloc(%p, %lu) at %s(): %lu, %s", data, size, func_, line_, file_);
// realloc it
return realloc(data, size);
}
static tb_bool_t tb_native_allocator_free(tb_allocator_ref_t allocator, tb_pointer_t data __tb_debug_decl__)
{
// trace
tb_trace_d("free(%p) at %s(): %lu, %s", data, func_, line_, file_);
// free it
return free(data);
}
その後、我々は、ネイティブ実装の下で私たち自身のディストリビューターを初期化します。
tb_allocator_t myallocator = {0};
myallocator.type = TB_ALLOCATOR_NATIVE;
myallocator.malloc = tb_native_allocator_malloc;
myallocator.ralloc = tb_native_allocator_ralloc;
myallocator.free = tb_native_allocator_free;
上記の点に留意され、非常に簡単ではありません__tb_debug_decl__
のようないくつかのデバッグ情報を宣言するマクロ、_file, _func, _line
記録する場合、そのようなメモリ割り当てなどの情報
、出てデバッグするときに印刷することができ、デバッグん、あなたはまた、いくつかに対処するために自分自身にこの情報を使用することができます高度なメモリテスト動作が、リリースのものは、取得することができません
使用する必要を扱うときに__tb_debug__
マクロを別々に処理します。。
myallocatorが経過tb_init
した後に、インターフェイスをtb_malloc/tb_ralloc/tb_free/...
他のすべてのTBOXメモリ割り当てインタフェースは新しいアロケータ割り当てに切断されます。。
tb_init(tb_null, &myallocator);
あなたが特定のアロケータから直接分配されるようにしたい場合はもちろん、あなたも達成するために直接割り当てるアロケータインターフェイスを呼び出すことができます。
tb_allocator_malloc(&myallocator, 10);
tb_allocator_ralloc(&myallocator, data, 100);
tb_allocator_free(&myallocator, data);
メモリ割り当てインタフェース
データ配信インタフェース
このようなインタフェースは、直接メモリのデータを割り当てられますが、返すことができるtb_pointer_t
データの種類を、ユーザーがそれを自分でやるのアクセスに強いターンを入力する必要があります。
!>このサフィックス0の単語とのインタフェースmalloc0は、割り当てられたメモリは自動的にメモリ動作を行うためにクリアされています。
tb_free(data)
tb_malloc(size)
tb_malloc0(size)
tb_nalloc(item, size)
tb_nalloc0(item, size)
tb_ralloc(data, size)
文字列の割り当てインタフェース
TBOXは、操作のデータ・タイプが直接であり、文字列型の便利な分布を提供するtb_char_t*
付加的な強い転写工程なしで、。
tb_malloc_cstr(size)
tb_malloc0_cstr(size)
tb_nalloc_cstr(item, size)
tb_nalloc0_cstr(item, size)
tb_ralloc_cstr(data, size)
バイトディスペンスインターフェース
これが唯一の違いは、デフォルトではないということです、データ配信インターフェースでtb_byte_t*
、アクセスするデータの読み取りおよび書き込みアクセス強い転送処理の種類を。
tb_malloc_bytes(size)
tb_malloc0_bytes(size)
tb_nalloc_bytes(item, size)
tb_nalloc0_bytes(item, size)
tb_ralloc_bytes(data, size)
構造体分配インターフェイスコンフィギュレーションデータ
あなたには、いくつかの構造体のデータを割り当てたい場合は、そのようなインタフェースは、強力なターン構造体型プロセスが付属しています。
tb_malloc_type(type)
tb_malloc0_type(type)
tb_nalloc_type(item, type)
tb_nalloc0_type(item, type)
tb_ralloc_type(data, item, type)
次のように使用されます:
typedef struct __xxx_t
{
tb_int_t dummy;
}xxx_t;
xxx_t* data = tb_malloc0_type(xxx_t);
if (data)
{
data->dummy = 0;
tb_free(data);
}
我々は、変換プロセスのタイプの必要性を排除している、見ることができるので、これはいくつかの便利な補助インターフェースを提供することです。
アドレスアライメントデータ分散インタフェース
データメモリアドレスの割り当てアウト私たちは、時には必要な場合は、これらのインタフェースを使用することができ、上で、指定したサイズに合わせて整列する必要があります。
tb_align_free(data)
tb_align_malloc(size, align)
tb_align_malloc0(size, align)
tb_align_nalloc(item, size, align)
tb_align_nalloc0(item, size, align)
tb_align_ralloc(data, size, align)
例えば:
tb_pointer_t data = tb_align_malloc(1234, 16);
データアドレスのデータが実際に整列16バイトを割り当てられています。
それは8バイト整列メモリデータ配信であれば、また次のインターフェイスを介して分配することができ、システムのようなインターフェースは、64-ビットを最適化され、それは何も特別な処理を行いません。
#if TB_CPU_BIT64
# define tb_align8_free(data) tb_free((tb_pointer_t)data)
# define tb_align8_malloc(size) tb_malloc(size)
# define tb_align8_malloc0(size) tb_malloc0(size)
# define tb_align8_nalloc(item, size) tb_nalloc(item, size)
# define tb_align8_nalloc0(item, size) tb_nalloc0(item, size)
# define tb_align8_ralloc(data, size) tb_ralloc((tb_pointer_t)data, size)
#else
# define tb_align8_free(data) tb_align_free((tb_pointer_t)data)
# define tb_align8_malloc(size) tb_align_malloc(size, 8)
# define tb_align8_malloc0(size) tb_align_malloc0(size, 8)
# define tb_align8_nalloc(item, size) tb_align_nalloc(item, size, 8)
# define tb_align8_nalloc0(item, size) tb_align_nalloc0(item, size, 8)
# define tb_align8_ralloc(data, size) tb_align_ralloc((tb_pointer_t)data, size, 8)
#endif
メモリテスト
デバッグモードでTBOXのメモリ割り当て、メモリリークやクロスボーダーのサポートを検出することができ、またメモリ割り当て位置、および関数呼び出しスタックの問題の特定の部分を特定します。
使用メモリTBOX検出にのみデバッグモードのコンパイルに切り替える必要があります。
$ xmake f -m debug
$ xmake
メモリリーク検出
!>リーク検出は、あなたが呼び出してください、プログラムの完全なを終了する必要がありますtb_exit()
インターフェイスを検出した後にトリガするために。
メモリリークの検出は、漏れがある場合は、出力端子にそこに詳述する、実装されたときにtb_exit()を呼び出して、プログラムが終了する前に、瞬間でなければなりません。
tb_void_t tb_demo_leak()
{
tb_pointer_t data = tb_malloc0(10);
}
出力:
[tbox]: [error]: leak: 0x7f9d5b058908 at tb_static_fixed_pool_dump(): 735, memory/impl/static_fixed_pool.c
[tbox]: [error]: data: from: tb_demo_leak(): 43, memory/check.c
[tbox]: [error]: [0x000001050e742a]: 0 demo.b 0x00000001050e742a tb_fixed_pool_malloc0_ + 186
[tbox]: [error]: [0x000001050f972b]: 1 demo.b 0x00000001050f972b tb_small_pool_malloc0_ + 507
[tbox]: [error]: [0x000001050f593c]: 2 demo.b 0x00000001050f593c tb_pool_malloc0_ + 540
[tbox]: [error]: [0x00000105063cd7]: 3 demo.b 0x0000000105063cd7 tb_demo_leak + 55
[tbox]: [error]: [0x00000105063e44]: 4 demo.b 0x0000000105063e44 tb_demo_memory_check_main + 20
[tbox]: [error]: [0x0000010505b08e]: 5 demo.b 0x000000010505b08e main + 878
[tbox]: [error]: [0x007fff8c95a5fd]: 6 libdyld.dylib 0x00007fff8c95a5fd start + 1
[tbox]: [error]: [0x00000000000002]: 7 ??? 0x0000000000000002 0x0 + 2
[tbox]: [error]: data: 0x7f9d5b058908, size: 10, patch: cc
メモリは、クロスボーダーを検出します
クロスボーダーの流出検出がリアルタイムで行われ、だけでなく、libcの計測に行われる、などの共通のstrcpy、memsetの、の使用は、検出をバックに行かなければなりません
tb_void_t tb_demo_overflow()
{
tb_pointer_t data = tb_malloc0(10);
if (data)
{
tb_memset(data, 0, 11);
tb_free(data);
}
}
出力:
[tbox]: [memset]: [overflow]: [0x0 x 11] => [0x7f950b044508, 10]
[tbox]: [memset]: [overflow]: [0x0000010991a1c7]: 0 demo.b 0x000000010991a1c7 tb_memset + 151
[tbox]: [memset]: [overflow]: [0x000001098a2d01]: 1 demo.b 0x00000001098a2d01 tb_demo_overflow + 97
[tbox]: [memset]: [overflow]: [0x000001098a3044]: 2 demo.b 0x00000001098a3044 tb_demo_memory_check_main + 20
[tbox]: [memset]: [overflow]: [0x0000010989a28e]: 3 demo.b 0x000000010989a28e main + 878
[tbox]: [memset]: [overflow]: [0x007fff8c95a5fd]: 4 libdyld.dylib 0x00007fff8c95a5fd start + 1
[tbox]: [memset]: [overflow]: [0x00000000000002]: 5 ??? 0x0000000000000002 0x0 + 2
[tbox]: [malloc]: [from]: data: from: tb_demo_overflow(): 12, memory/check.c
[tbox]: [malloc]: [from]: [0x0000010992662a]: 0 demo.b 0x000000010992662a tb_fixed_pool_malloc0_ + 186
[tbox]: [malloc]: [from]: [0x0000010993892b]: 1 demo.b 0x000000010993892b tb_small_pool_malloc0_ + 507
[tbox]: [malloc]: [from]: [0x00000109934b3c]: 2 demo.b 0x0000000109934b3c tb_pool_malloc0_ + 540
[tbox]: [malloc]: [from]: [0x000001098a2cd7]: 3 demo.b 0x00000001098a2cd7 tb_demo_overflow + 55
[tbox]: [malloc]: [from]: [0x000001098a3044]: 4 demo.b 0x00000001098a3044 tb_demo_memory_check_main + 20
[tbox]: [malloc]: [from]: [0x0000010989a28e]: 5 demo.b 0x000000010989a28e main + 878
[tbox]: [malloc]: [from]: [0x007fff8c95a5fd]: 6 libdyld.dylib 0x00007fff8c95a5fd start + 1
[tbox]: [malloc]: [from]: [0x00000000000002]: 7 ??? 0x0000000000000002 0x0 + 2
[tbox]: [malloc]: [from]: data: 0x7f950b044508, size: 10, patch: cc
[tbox]: [malloc]: [from]: data: first 10-bytes:
[tbox]: ===================================================================================================================================================
[tbox]: 00000000 00 00 00 00 00 00 00 00 00 00 ..........
[tbox]: [error]: abort at tb_memset(): 255, libc/string/memset.c
オーバーラップするカバレッジを検出するメモリ
二つのメモリコピーの重複が発生した場合、不具合を生じる、部分的に上書きされたデータが存在してもよい、TBOXにはまた、いくつかの検出を行いました。
tb_void_t tb_demo_overlap()
{
tb_pointer_t data = tb_malloc(10);
if (data)
{
tb_memcpy(data, (tb_byte_t const*)data + 1, 5);
tb_free(data);
}
}
輸出
[tbox]: [memcpy]: [overlap]: [0x7fe9b5042509, 5] => [0x7fe9b5042508, 5]
[tbox]: [memcpy]: [overlap]: [0x000001094403b8]: 0 demo.b 0x00000001094403b8 tb_memcpy + 632
[tbox]: [memcpy]: [overlap]: [0x000001093c99f9]: 1 demo.b 0x00000001093c99f9 tb_demo_overlap + 105
[tbox]: [memcpy]: [overlap]: [0x000001093c9a44]: 2 demo.b 0x00000001093c9a44 tb_demo_memory_check_main + 20
[tbox]: [memcpy]: [overlap]: [0x000001093c0c8e]: 3 demo.b 0x00000001093c0c8e main + 878
[tbox]: [memcpy]: [overlap]: [0x007fff8c95a5fd]: 4 libdyld.dylib 0x00007fff8c95a5fd start + 1
[tbox]: [memcpy]: [overlap]: [0x00000000000002]: 5 ??? 0x0000000000000002 0x0 + 2
[tbox]: [malloc]: [from]: data: from: tb_demo_overlap(): 58, memory/check.c
[tbox]: [malloc]: [from]: [0x0000010945eadb]: 0 demo.b 0x000000010945eadb tb_small_pool_malloc_ + 507
[tbox]: [malloc]: [from]: [0x0000010945b23c]: 1 demo.b 0x000000010945b23c tb_pool_malloc_ + 540
[tbox]: [malloc]: [from]: [0x000001093c99c7]: 2 demo.b 0x00000001093c99c7 tb_demo_overlap + 55
[tbox]: [malloc]: [from]: [0x000001093c9a44]: 3 demo.b 0x00000001093c9a44 tb_demo_memory_check_main + 20
[tbox]: [malloc]: [from]: [0x000001093c0c8e]: 4 demo.b 0x00000001093c0c8e main + 878
[tbox]: [malloc]: [from]: [0x007fff8c95a5fd]: 5 libdyld.dylib 0x00007fff8c95a5fd start + 1
[tbox]: [malloc]: [from]: [0x00000000000002]: 6 ??? 0x0000000000000002 0x0 + 2
[tbox]: [malloc]: [from]: data: 0x7fe9b5042508, size: 10, patch: cc
[tbox]: [malloc]: [from]: data: first 10-bytes:
[tbox]: ===================================================================================================================================================
[tbox]: 00000000 CC CC CC CC CC CC CC CC CC CC ..........
[tbox]: [error]: abort at tb_memcpy(): 125, libc/string/memcpy.c
メモリデュアルリリース検出
tb_void_t tb_demo_free2()
{
tb_pointer_t data = tb_malloc0(10);
if (data)
{
tb_free(data);
tb_free(data);
}
}
輸出
[tbox]: [assert]: expr[((impl->used_info)[(index) >> 3] & (0x1 << ((index) & 7)))]: double free data: 0x7fd93386c708 at tb_static_fixed_pool_free(): 612, memory/impl/static_fixed_pool.c
[tbox]: [0x0000010c9f553c]: 0 demo.b 0x000000010c9f553c tb_static_fixed_pool_free + 972
[tbox]: [0x0000010c9ee7a9]: 1 demo.b 0x000000010c9ee7a9 tb_fixed_pool_free_ + 713
[tbox]: [0x0000010ca01ff5]: 2 demo.b 0x000000010ca01ff5 tb_small_pool_free_ + 885
[tbox]: [0x0000010c9fdb4f]: 3 demo.b 0x000000010c9fdb4f tb_pool_free_ + 751
[tbox]: [0x0000010c96ac8e]: 4 demo.b 0x000000010c96ac8e tb_demo_free2 + 158
[tbox]: [0x0000010c96ae44]: 5 demo.b 0x000000010c96ae44 tb_demo_memory_check_main + 20
[tbox]: [0x0000010c96208e]: 6 demo.b 0x000000010c96208e main + 878
[tbox]: [0x007fff8c95a5fd]: 7 libdyld.dylib 0x00007fff8c95a5fd start + 1
[tbox]: [0x00000000000002]: 8 ??? 0x0000000000000002 0x0 + 2
[tbox]: [error]: free(0x7fd93386c708) failed! at tb_demo_free2(): 37, memory/check.c at tb_static_fixed_pool_free(): 649, memory/impl/static_fixed_pool.c
[tbox]: [error]: data: from: tb_demo_free2(): 33, memory/check.c
[tbox]: [error]: [0x0000010c9ee42a]: 0 demo.b 0x000000010c9ee42a tb_fixed_pool_malloc0_ + 186
[tbox]: [error]: [0x0000010ca0072b]: 1 demo.b 0x000000010ca0072b tb_small_pool_malloc0_ + 507
[tbox]: [error]: [0x0000010c9fc93c]: 2 demo.b 0x000000010c9fc93c tb_pool_malloc0_ + 540
[tbox]: [error]: [0x0000010c96ac27]: 3 demo.b 0x000000010c96ac27 tb_demo_free2 + 55
[tbox]: [error]: [0x0000010c96ae44]: 4 demo.b 0x000000010c96ae44 tb_demo_memory_check_main + 20
[tbox]: [error]: [0x0000010c96208e]: 5 demo.b 0x000000010c96208e main + 878
[tbox]: [error]: [0x007fff8c95a5fd]: 6 libdyld.dylib 0x00007fff8c95a5fd start + 1
[tbox]: [error]: [0x00000000000002]: 7 ??? 0x0000000000000002 0x0 + 2
[tbox]: [error]: data: 0x7fd93386c708, size: 10, patch: cc
[tbox]: [error]: data: first 10-bytes:
[tbox]: ===================================================================================================================================================
[tbox]: 00000000 00 00 00 00 00 00 00 00 00 00 ..........
[tbox]: [error]: abort at tb_static_fixed_pool_free(): 655, memory/impl/static_fixed_pool.c