ESP-IDF下为Address Sanitizer重定义std::free/std::malloc的方法
解决ESP32 C++应用中ASAN适配std::malloc/std::free的编译错误
问题场景
调试ESP32上的C应用内存损坏问题时,使用Erich Styger的tinyK22_FreeRTOS_ASAN代码,其中C语言的malloc()/free()重定义可以正常编译,但因为未处理C标准库的std::malloc和std::free,出现如下编译错误:
In file included from /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/8.4.0/stdlib.h:36, from ../../ext/esp-idf/components/newlib/platform_include/assert.h:21, from /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/sys-include/sys/reent.h:503, from ../../ext/esp-idf/components/newlib/platform_include/sys/reent.h:17, from /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/sys-include/stdio.h:60, from ../../ext/esp-idf/components/esp_common/include/esp_err.h:10, from ../../ext/esp-idf/components/driver/include/driver/gpio.h:10, from ../../include/GfCommon.h:19, from ../../include/GfLogger.h:21, from ../../include/GfInit.h:12, from GfMainApp.cpp:14: /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/8.4.0/cstdlib:147:11: error: '::free' has not been declared using ::free; ^~~~ /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/8.4.0/cstdlib:151:11: error: '::malloc' has not been declared using ::malloc; ^~~~~~ In file included from ../../ext/esp-idf/components/newlib/platform_include/assert.h:21, from /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/sys-include/sys/reent.h:503, from ../../ext/esp-idf/components/newlib/platform_include/sys/reent.h:17, from /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/sys-include/stdio.h:60, from ../../ext/esp-idf/components/esp_common/include/esp_err.h:10, from ../../ext/esp-idf/components/driver/include/driver/gpio.h:10, from ../../include/GfCommon.h:19, from ../../include/GfLogger.h:21, from ../../include/GfInit.h:12, from GfMainApp.cpp:14: /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/8.4.0/stdlib.h:61:12: error: 'std::free' has not been declared using std::free; ^~~~ /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/8.4.0/stdlib.h:65:12: error: 'std::malloc' has not been declared using std::malloc;
尝试用#define std::free直接重定义会报错,自行实现std::free也无效,修改后仍出现如下错误:
In file included from /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/8.4.0/stdlib.h:36, from ../../ext/esp-idf/components/newlib/platform_include/assert.h:21, from /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/sys-include/sys/reent.h:503, from ../../ext/esp-idf/components/newlib/platform_include/sys/reent.h:17, from /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/sys-include/stdio.h:60, from ../../ext/esp-idf/components/esp_common/include/esp_err.h:10, from ../../ext/esp-idf/components/driver/include/driver/gpio.h:10, from ../../include/GfCommon.h:19, from ../../include/GfLogger.h:21, from ../../include/GfInit.h:12, from GfMainApp.cpp:14: /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/8.4.0/cstdlib:147:11: error: '::free' has not been declared using ::free; ^~~~ In file included from ../../ext/esp-idf/components/newlib/platform_include/assert.h:21, from /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/sys-include/sys/reent.h:503, from ../../ext/esp-idf/components/newlib/platform_include/sys/reent.h:17, from /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/sys-include/stdio.h:60, from ../../ext/esp-idf/components/esp_common/include/esp_err.h:10, from ../../ext/esp-idf/components/driver/include/driver/gpio.h:10, from ../../include/GfCommon.h:19, from ../../include/GfLogger.h:21, from ../../include/GfInit.h:12, from GfMainApp.cpp:14: /usr/local/espTools/xtensa-esp32-elf/xtensa-esp32-elf/include/c++/8.4.0/stdlib.h:61:12: error: 'std::free' has not been declared using std::free; ^~~~
正确实现方案
核心是先保留原始内存函数的声明,再替换为ASAN版本,同时为C++标准库提供std命名空间下的实现,避免编译器找不到符号:
- 调整头文件包含顺序:确保ASAN的重定义代码在所有C/C++标准库头文件之前被包含。
- 保存原始函数指针:避免递归调用,同时确保原始内存函数能被访问。
- 实现std命名空间的内存函数:为C++标准库提供对应的符号。
具体代码示例:
// 先包含标准库头文件,获取原始malloc/free的声明 #include <stdlib.h> #if McuASAN_CONFIG_IS_ENABLED && McuASAN_CONFIG_CHECK_MALLOC_FREE // 声明原始内存函数,用于在ASAN版本中调用 extern "C" { void* __real_malloc(size_t size); void __real_free(void* ptr); } // 重定义全局malloc/free为ASAN版本 #define malloc __asan_malloc #define free __asan_free // ASAN版本的malloc实现,添加内存检查逻辑 void* __asan_malloc(size_t size) { // 这里添加你的ASAN内存分配检查逻辑(比如记录分配地址、大小等) void* ptr = __real_malloc(size); // 示例:标记内存块为已分配 // McuASAN_RecordAllocation(ptr, size); return ptr; } // ASAN版本的free实现,添加内存检查逻辑 void __asan_free(void* ptr) { if (ptr == NULL) { return; } // 这里添加你的ASAN内存释放检查逻辑(比如检查是否重复释放、越界等) // McuASAN_CheckFree(ptr); __real_free(ptr); } #ifdef __cplusplus namespace std { // 为C++标准库提供std::malloc,调用ASAN版本 inline void* malloc(size_t size) { return __asan_malloc(size); } // 为C++标准库提供std::free,调用ASAN版本 inline void free(void* ptr) { __asan_free(ptr); } } #endif #endif
额外注意事项
- 在ESP-IDF环境中,若使用newlib的重入版本(
_malloc_r/_free_r),需要同步处理这些函数的重定义,确保覆盖所有内存分配路径。 - 确保ASAN的相关检查函数(如
McuASAN_RecordAllocation、McuASAN_CheckFree)已正确实现,避免未定义引用错误。
内容的提问来源于stack exchange,提问作者Danny
相关产品推荐
相关产品推荐

