#include <rtc_api.h>
RTC_Result _rtc_check_free(void *ptr);
RTC_Result _rtc_check_malloc(size_t size);
RTC_Result _rtc_check_realloc(void *ptr, size_t size);
RTC_Result _rtc_check_malloc_result(void *ptr, size_t size);
RTC_Result _rtc_check_realloc_result(void *old_ptr, void *new_ptr, size_t new_size);
RTC_Result _rtc_hide_region(void *ptr, size_t size);
RTC_Result _rtc_off(void );
RTC_Result _rtc_on(void );
RTC_Result _rtc_record_free(void *ptr);
RTC_Result _rtc_record_malloc(void *ptr, size_t size);
RTC_Result _rtc_record_realloc(void *old_ptr, void *new_ptr, size_t new_size);
void _rtc_report_error(RTC_Result err);
MT-安全
実行時検査 (RTC) では、プログラム内のすべての割り当てと解放を追跡できるように、共有ライブラリ libc.so 内の標準ヒープ管理ルーチンを使用する必要があります。多くのアプリケーションでは、malloc がない状態または最初から、独自のメモリー管理ルーチンを作成しています。ユーザーが独自のプライベートアロケータを使用する場合、RTC はそのアロケータを自動的には追跡できません。ただし、RTC には、プライベートアロケータを使用するための API が用意されており、プライベートアロケータを標準ヒープアロケータと同じように扱うことができます。
実行時検査 API 関数には、RTC で非標準メモリーアロケータを使用するためのインタフェースが用意されています。このインタフェースは、malloc、free、および realloc をプライベートメモリーアロケータであるかのようにサポートします。これにより、メモリー領域の割り当てや解放を行うときに、API 関数を使用して RTC のメモリーマップを更新できます。API は、アロケータを使用するプログラムによるメモリーアクセスを RTC で検査できるようにします。
「プライベートアロケータ」がプログラムヒープを使用しないときには、RTC エラーレポートは若干異なる場合があります。標準ヒープブロックを参照するメモリーアクセスエラーが発生した場合、RTC エラーレポートには通常、ヒープブロック割り当ての位置が含まれます。この場合には、この位置が報告されない可能性があります。
RTC API のすべてのエントリポイントは、RTC で実行したときに、RTC ライブラリ内の適切な関数の呼び出しに変わるマクロです。これらを使用するために、条件付きでコードをコンパイルする必要はありません。
_rtc_check_free() - free のような関数に渡された引数が有効であるかどうかを調べるために呼び出されます。
_rtc_check_malloc() - malloc のような関数に渡された引数が有効であるかどうかを調べるために呼び出されます。
_rtc_check_realloc() - realloc のような関数に渡された引数が有効であるかどうかを調べるために呼び出されます。
_rtc_check_malloc_result() - size バイトの割り当ての結果として生成されたポインタ ptr が malloc のような関数の有効な結果であるかどうかを調べるために呼び出されます。
_rtc_check_realloc_result() - old_ptr を size バイトに再割り当てした結果として生成されたポインタ new_ptr が realloc() のような関数の有効な結果であるかどうかを調べるために呼び出されます。
_rtc_hide_region() - ptr で始まる size バイトを RTC メモリーマップでアクセスできないものとしてマークします。オンデマンドで割り当てられる sbrk(2) や mmap(2) で取得されるメモリーへのアクセスを無効にするために使用されます。
_rtc_off() および _rtc_on() - RTC がアクセスできないとみなしているメモリー領域でのデータ構造を操作しているときに、プライベートアロケータがメモリーアクセス検査を中断できるようにします。アロケータは、このようなメモリー領域にアクセスする前に _calling _rtc_off() を呼び出して検査をオフにすることができ、終了時に _rtc_on() を呼び出して検査をオンに戻すことができます。
_rtc_record_free()、__rtc_record_malloc()、および __rtc_record_realloc() - プライベートアロケータがメモリーブロックを割り当てたり解放したときに生じるメモリー領域のアクセシビリティーの変更を反映するように RTC のメモリーマップを変更します。
_rtc_report_error() - エラーを報告します。
操作が成功した場合、_rtc_check_free()、_rtc_check_malloc()、_rtc_check_realloc()、_rtc_check_malloc_result()、_rtc_check_realloc_result()、_rtc_hide_region()、_rtc_record_free()、_rtc_record_malloc()、および _rtc_record_realloc() はすべて RTC_SUCCESS を戻します。成功しなかった場合、_rtc_report_error() に渡すことのできるエラー結果を戻します。
次の RTC API 関数の呼び出し例は、プライベートアロケータで RTC のメモリーマップを最新の状態に維持できるようにする方法について示しています。
使用例 1 あとで割り当てるためのメモリーを取得します。{ size_t large_block = size_needed; void *old_break_ptr = sbrk((int)large_block); RTC_Result result; result = _rtc_hide_region(old_break_ptr, large_block); if (result != RTC_success) return NULL; return old_break_ptr; }使用例 2 ブロックを割り当てます (malloc のような関数)。
{ size_t block_size = request_size; void *ptr = NULL; RTC_Result result = RTC_SUCCESS; result = _rtc_check_malloc(block_size); if (result == RTC_SUCCESS) { _rtc_off(); ptr = private_alloc(block_size); _rtc_on(); result = _rtc_record_malloc(ptr, block_size); if (result == RTC_SUCCESS) { /* If we had guard blocks around the block of memory * we would return to the user then we would mark * the guard blocks as inaccessible by using * _rtc_hide_region() */ } } if (result != RTC_SUCCESS) _rtc_report_error(result); return ptr; }使用例 3 ブロックを解放します (free のような関数)。
{ RTC_Result result = RTC_SUCCESS; result = _rtc_check_free(ptr); if (result == RTC_SUCCESS) { _rtc_off(); private_free(ptr); _rtc_on(); (void)_rtc_record_free(ptr); } else { _rtc_report_error(result); } }使用例 4 ブロックを再割り当てします (realloc のような関数)。
{ void *new_ptr = NULL; size_t size = request_size; void *old_ptr; RTC_Result result = RTC_SUCCESS; result = _rtc_check_realloc(old_ptr, size); if (result == RTC_SUCCESS) { _rtc_off(); new_ptr = private_realloc(old_block_record, size); _rtc_on(); result = _rtc_check_realloc_result(old_ptr, new_ptr, size); if (result == RTC_SUCCESS) result = _rtc_record_realloc(old_ptr, new_ptr, size); } if (result != RTC_SUCCESS) _rtc_report_error(result); return new_ptr; }
dbx(1), mmap(2), sbrk(2)