#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-Safe(MT 安全)
运行时检查 (Runtime Checking, RTC) 要求使用共享库 libc.so 中的标准堆管理例程,以便 RTC 跟踪程序中的所有分配和取消分配情况。许多应用程序在 malloc-free 的基础上或从头编写自己的内存管理例程。当您使用自己的(称为“专用”)分配器时,RTC 无法自动跟踪它们。但是,RTC 针对专用分配器的使用提供了一个 API,该 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 的内存映射最新。
Example 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; }Example 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; }Example 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); } }Example 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)