ヒープの整合性違反の検出
説明
さまざまなヒープの整合性違反をチェックします。チェックは手動でトリガしたり、ヒープインターフェースの使用に対して定期的な間隔でトリガされるよう設定できます。このチェックを有効にして検出できる整合性の問題には、以下のものがあります。
内部ヒープ構造の破壊。ほとんどの場合、これはポインタ式からのライトアクセスが正しくないことが原因です。間違ったライトアクセスを探すには、境界チェックを使用してください。
割り当てられたメモリの領域外でのライトアクセス。たとえば以下のようなものです。
char * p = (char *)malloc(100); /* Memory is allocated. */ ... p[100] = ... /* This write access is out of bounds. */
ヒープブロックの境界の外でのライトアクセス、およびヒープブロックの前後でガードを変更するライトアクセスが検出されます。その他のライトアクセスは検出されません。
解放済みメモリに対するライトアクセス。たとえば以下のようなものです。
char * p = (char *)malloc(...); /* Memory is allocated. */ ... free(p); /* Memory is freed. */ ... p[...] = ... /* Write access to freed memory. */
元の
pを含むメモリがpの書込みより前に再び割り当てられる場合、このエラーは通常は検出されません。遅延のある解放リスト(以下を参照)を使用することで、このエラーを検出できます。
チェックを実行する理由
たとえばヒープブロックの誤用などの理由で、アプリケーションが間違ってある時点でヒープに書き込んでいると思われる場合は、チェック済みヒープを使用してください。
使用方法
リンカオプション :‑‑debug_heap
IDE で、 [プロジェクト]>[オプション]>[ランタイム解析]>[ランタイム解析]
チェック済みヒープは、アプリケーション全体にわたって通常のヒープを置換します。チェック済みヒープには、追加のヒープとスタックリソースが必要です。アプリケーションに 10 KB 以上のヒープと 4 KB のスタックがあることを確認してください。
ヒープの整合性違反を検出する目的で、iar_dlmalloc.h に定義された以下の関数を使用できます。
size_t __iar_check_heap_integrity(void);この関数を使用して、ヒープの整合性を検証します。損傷が見つかった場合は、それが報告されます。リターン値は見つかった問題の件数です。報告される損傷エラーの件数には限りがあります。この上限は、
__iar_set_integrity_report_limit関数を使用して変更できます。最終のメッセージが生成されたときのみ、実行が停止します。報告されるメッセージのデフォルト件数は10です。__iar_check_heap_integrityの呼び出しでは、ヒープに損傷がある場合に呼び出し元に返すという保証はありません。size_t __iar_set_heap_check_frequency(size_t interval);この関数を使用して、定期的にヒープ整合性チェックを実行する頻度を指定します。デフォルトでは、定期的チェックはオフに設定されています(
interval= 0)。intervalが正の数値の場合、整合性はinterval:回目のヒープ演算ごとにチェックされ、free/malloc/new/delete/realloc/などの呼び出しが1回の演算として数えられます。この関数は古い間隔を返します。つまり、必要があれば状態を復元できます。ヒープチェックは、アプリケーションプログラムの信頼できる部分を実行する際は間隔を長くしたり、オフにすることも可能です。また、アプリケーションでヒープエラーが含まれる可能性が高い部分を実行するときは、チェックの間隔を小さくすることができます。size_t __iar_set_delayed_free_size(size_t size);この機能を使用して、解放された遅延リストの最大サイズを指定します。デフォルトでは、解放済み遅延リストはオフに設定されています(
size= 0)。この関数はリストの実際のサイズには影響せず、最大値のみを変更します。この関数は前回の値を返すため、必要があれば復元が可能です。解放済み遅延リストを使用して、解放済みヒープブロックを使用するアプリケーション内のアドレスを見つけます。以下を検出する際に役立ちます。
解放済みの古いヒープブロックポインタが、新しい割当済みのヒープブロックポインタと混在している場合。解放済み遅延リストは解放済みヒープブロックの再利用を遅らせるため、アプリケーションの動作が変わり、この種類の問題を検出できることがあります。
すでに解放されているヒープブロックに書き込みます。ヒープブロックが解放済み遅延リストにあると、実際に解放されるときのものとは異なる特定の内容を取得し、ヒープ整合性チェックでヒープブロックに対するこれらの間違ったライトアクセスを検出することができます。
size_t __iar_free_delayed_free_size(size_t count);この関数を使用して、解放済み遅延内に存在する要素の数が最大でも
count個になるように制御できます。余分な要素は解放されます(最も古いものから変更されます)。リストの最大サイズには影響しません。現在の要素の数のみが変更されます。この関数を呼び出しても、countがリストの現在のサイズより大きい場合には効果はありません。この関数は解放済み要素の数を返します。
仕組み
チェック済みヒープは、アプリケーション全体にわたって通常のヒープを置換します。
解放済み遅延リストは、free 呼び出しのキューメカニズムです。free、またはメモリをヒープに返す同等のメモリ処理を呼び出す際、最近解放されたポインタが、実際に解放される代わりに、解放待ちのキューに入ります。遅延リストの最大サイズを超過すると、解放済み遅延リストで最大サイズを超えた最も古い要素が実際に解放されます。
チェック済みヒープで報告されるすべてのエラーは、何らかの理由で損傷したヒープブロックについて言及します。チェック済みヒープは、ヒープブロックを損傷したユーザや損傷した時期については情報を提供しません。__iar_debug_check_heap_integrity関数を呼び出して、アプリケーション実行時の整合性を検証し、潜在的な候補のリストを絞り込むことができます。
以下に例を示します。
... __iar_debug_check_heap_integrity(); /* Pre-check */ my_function(..., ..., ...); __iar_debug_check_heap_integrity(); /* Post-check */ ...
事後のチェックで事前のチェックで報告されない問題が見つかった場合、my_function でヒープが損傷した可能性があります。
チェック済みヒープはリソースを消費します。
チェック済みヒープは、通常のヒープ実装に比べてより多くのROM容量を必要とします。
すべてのヒープ処理にはチェック済みヒープでより多くの時間が必要です。
チェック済みヒープの各ヒープブロックには、記録のための追加の容量が含まれます。このため、アプリケーションのRAM使用量が増えることになります。
ライブラリにより提供されるチェック済みヒープを参照してください。
例
C-RUNランタイムエラー解析を使用するにあたってに記載された手順に従ってください。[チェック済みヒープ]オプションを使用します。
これは、実行時に識別されるソースコードの一例です。
C-RUN はヒープの整合性違反を報告します。これは、リストされるメッセージの一例です。
