作者热门文章
- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 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
把大量的分配变成一个真正的问题。
$ 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 Code和
CI Pipeline Results这在 gitlab 上可用。
#ifdef __SANITIZE_ADDRESS__
把东西从 sanitizer 中藏起来不知何故在作弊。
operator>>
期间跳过 ASAN 的分配器填充称呼?在一般情况下,在调用分配内存的第三方函数的紧密循环中,我如何使用
-fsanitize=address
避免巨大的内存占用?
最佳答案
正如您所说,AddressSanitizer 将延迟释放内存的重用,以帮助捕获释放后使用错误。此功能称为“隔离”,用于它的内存量可在运行时配置,请参阅 https://github.com/google/sanitizers/wiki/AddressSanitizerFlags .例如,如果您设置环境变量 ASAN_OPTIONS
至 quarantine_size_mb=4
在运行您的程序之前,它应该将使用的内存量限制为 4 兆字节。
这不是特定于有问题的调用,因此它不能完全解决您的问题,但我认为它将解决您“如何在内存不足的机器上使用 AddressSanitizer”的潜在问题。
关于c++ - 如何从 ASAN 的紧密循环中排除分配?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65721208/
我是一名优秀的程序员,十分优秀!