gpt4 book ai didi

c++ - 如何从 ASAN 的紧密循环中排除分配?

转载 作者:行者123 更新时间:2023-12-03 10:05:08 24 4
gpt4 key购买 nike

previous question ,发现使用最新版本的 GNU libstdc++ 从 a space-separated human-readable file 读取一系列数字( mirror ) 导致大量分配,随文件大小线性缩放。
鉴于上面链接的文件和这个测试程序:

#include <fstream>

int main(int, char**) {
std::ifstream ww15mgh("ww15mgh.grd");
double value;
while (ww15mgh >> value);
return 0;
}
Valgrind --tool=memcheck报告:
==523661==   total heap usage: 1,038,970 allocs, 1,038,970 frees, 59,302,487 
因为这百万分配中的每一个都在 operator>> 之前立即被释放。返回,没有泄漏并且程序在发布版本中的实际内存占用很小(81KB)。但是,编译 -fsanitize=address把大量的分配变成一个真正的问题。
以下是上述程序的总内存占用,运行和不运行 ASAN:
$ g++ stackoverflow.cpp -o _build/stackoverflow
$ /usr/bin/time -v _build/stackoverflow |& grep 'm r'
Maximum resident set size (kbytes): 3512
$ g++ stackoverflow.cpp -o _build/stackoverflow_asan -fsanitize=address
$ /usr/bin/time -v _build/stackoverflow_asan |& grep 'm r'
Maximum resident set size (kbytes): 125196
125MB 似乎不是一个大问题,但在一个更大的单元测试程序运行在嵌入式 ARM 板上并多次调用此函数的上下文中,它运行我的 ARM CI 环境内存不足。
此特定情况的解决方法
#include <fstream>
#include <string>
#include <cstdio>

int main(int, char**) {
std::ifstream ww15mgh("ww15mgh.grd");
double value;
#if defined(__SANITIZE_ADDRESS__) && (defined(__GLIBCXX__) || defined(__GLIBCPP__))
std::string text;
while (ww15mgh >> text)
value = std::strtod(text.data(), nullptr);
#else
while (ww15mgh >> value);
#endif
return 0;
}
使用这个预处理器门会产生更易于管理的总内存占用:
$ g++ stackoverflow_workaround.cpp -o _build/stackoverflow_workaround_asan -fsanitize=address
$ /usr/bin/time -v _build/stackoverflow_workaround_asan |& grep 'm r'
Maximum resident set size (kbytes): 6396
这是因为 libstdc++ 的 operator>>(ifstream&, string&) 都没有也不是 glibc 的 strtod其中有多余的分配,这可以通过欺骗解决方法在 valgrind 下运行来看到:
$ g++ stackoverflow_workaround.cpp -D__SANITIZE_ADDRESS__
$ valgrind --tool=memcheck --leak-check=yes ./a.out |& grep 'total heap'
==2483624== total heap usage: 3 allocs, 3 frees, 81,368 bytes allocated
Sample CodeCI Pipeline Results这在 gitlab 上可用。
在这一点上,我的 CI 不再耗尽内存和崩溃,所以我的同事可以继续他们的生活。然而,我想用 #ifdef __SANITIZE_ADDRESS__ 把东西从 sanitizer 中藏起来不知何故在作弊。
问题
有没有办法让原始程序在 ASAN 下运行,但在 operator>> 期间跳过 ASAN 的分配器填充称呼?在一般情况下,在调用分配内存的第三方函数的紧密循环中,我如何使用 -fsanitize=address 避免巨大的内存占用?

最佳答案

正如您所说,AddressSanitizer 将延迟释放内存的重用,以帮助捕获释放后使用错误。此功能称为“隔离”,用于它的内存量可在运行时配置,请参阅 https://github.com/google/sanitizers/wiki/AddressSanitizerFlags .例如,如果您设置环境变量 ASAN_OPTIONSquarantine_size_mb=4在运行您的程序之前,它应该将使用的内存量限制为 4 兆字节。
这不是特定于有问题的调用,因此它不能完全解决您的问题,但我认为它将解决您“如何在内存不足的机器上使用 AddressSanitizer”的潜在问题。

关于c++ - 如何从 ASAN 的紧密循环中排除分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65721208/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com