将内存清理程序与libstdc++一起使用
Using memory sanitizer with libstdc++
我希望使用clang中的-fsanitize=memory
标志来分析如下程序:
#include <string>
#include <iostream>
#include <fstream>
using namespace std;
void writeToFile(){
ofstream o;
o.open("dum");
o<<"test"<<endl; //The error is here.
//It does not matter if the file is opened this way,
//or with o("dum");
o.close();
}
int main(){
writeToFile();
}
据我所知,这个程序是正确的,但当我使用clang++ san.cpp -fsanitize=memory
时,它会失败(在运行时),原因是:
UMR in __interceptor_write at offset 0 inside [0x64800000e000, +5)
==9685== WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x7f48d0899ae5 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x7bae5)
#1 0x7f48d08d1787 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb3787)
#2 0x7f48d08d21e2 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb41e2)
#3 0x7f48d08cfd1e (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb1d1e)
#4 0x7f48d08b1f2d (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x93f2d)
#5 0x7f48d16d60f5 in writeToFile() /home/daniel/programming/test/santest.cpp:10
#6 0x7f48d16d61f4 in main /home/daniel/programming/test/santest.cpp:15
#7 0x7f48d0261de4 (/lib/x86_64-linux-gnu/libc.so.6+0x21de4)
#8 0x7f48d16d5e42 in _start (/home/daniel/programming/test/a.out+0x61e42)
SUMMARY: MemorySanitizer: use-of-uninitialized-value ??:0 ??
我怎样才能使它正常工作?
Clang 3.5版,stdlibc++6版
代码当然很好,但许多类似的错误是由clang的内存清理工具的以下要求引起的:
MemoryManitizer(没有动态组件)要求整个程序包括库的代码(在某种程度上除了libc/libm/libpthread)都是插入指令的。
从这里
您正在使用libstdc++的cplusplus运行时是未调试的,会导致错误。不幸的是,您将不得不遵循该链接中描述的一个有点麻烦的过程来重建插入指令的libstdc++或切换到libc++(更简单的ish)
目前最简单的方法是使用memorysanitizer构建libc++,然后将您的程序与之链接。
这是我一段时间前的做法,因为我无法处理libc++构建系统:https://code.google.com/p/memory-sanitizer/source/browse/bootstrap/build_libcxx.sh
我听说libc++方面有所改进,也许可以像往常一样构建它(使用CC=/path/to/clang CFLAGS=-fsanitize=memory之类的东西)。
我怎样才能使它正常工作?
您还可以unpoison
触发查找的内存。但(对我来说)不清楚哪个变量是基于所显示的堆栈跟踪的。
以下是如何解除对内存的锁定,但此示例适用于与FD_SET
和FD_ZERO
一起使用的内存。您仍然需要找到引起它的变量的名称(我不确定指定积分内存地址的效果如何)。
#include <sanitizer/msan_interface.h>
...
__msan_unpoison(&readfds, sizeof(readfds));
__msan_unpoison(&writefds, sizeof(writefds));
UMR in __interceptor_write at offset 0 inside [0x64800000e000, +5)
==9685== WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x7f48d0899ae5 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x7bae5)
#1 0x7f48d08d1787 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb3787)
#2 0x7f48d08d21e2 (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb41e2)
#3 0x7f48d08cfd1e (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0xb1d1e)
#4 0x7f48d08b1f2d (/usr/lib/x86_64-linux-gnu/libstdc++.so.6+0x93f2d)
#5 0x7f48d16d60f5 in writeToFile() /home/daniel/programming/test/santest.cpp:10
#6 0x7f48d16d61f4 in main /home/daniel/programming/test/santest.cpp:15
#7 0x7f48d0261de4 (/lib/x86_64-linux-gnu/libc.so.6+0x21de4)
#8 0x7f48d16d5e42 in _start (/home/daniel/programming/test/a.out+0x61e42)
你可以通过运行获得更多关于罪犯的信息
./myprog.exe 2>&1 | /usr/bin/asan_symbolize
例如,我正在尝试测试一个输出与您类似的程序:
$ ./cryptest.exe v 2>&1 | /usr/bin/asan_symbolize
==26988== WARNING: MemorySanitizer: use-of-uninitialized-value
#0 0x7f51903b2ca8 in _ZNSt8_Rb_treeISsSt4pairIKSsPvESt10_Select1stIS3_ESt4lessISsESaIS3_EE14_M_lower_boundEPSt13_Rb_tree_nodeIS3_ESC_RS1_ /usr/bin/../lib/gcc/x86_64-linux-gnu/4.9/../../../../include/c++/4.9/bits/stl_tree.h:1260 (discriminator 1)
...
如果你要接受一些惩罚,你可以通过c++filt
管道传输损坏的名称,并获得一个未损坏的名称:
$ echo " _ZNSt8_Rb_treeISsSt4pairIKSsPvESt10_Select1stIS3_ESt4lessISsESaIS3_EE14_M_lower_boundEPSt13_Rb_tree_nodeIS3_ESC_RS1_" | c++filt
std::_Rb_tree<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, void*>, std::_Select1st<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, void*> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, void*> > >::_M_lower_bound(std::_Rb_tree_node<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, void*> >*, std::_Rb_tree_node<std::pair<std::basic_string<char, std::char_traits<char>, std::allocator<char> > const, void*> >*, std::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)
最后,根据Msan人员的说法,您确实需要一个C++运行时的工具化构建。他们还建议您为此使用LLVM的libc++
。请参阅Memory Sanitizer Libcxx HowTo和How to unmison a C++std::string?在Memory Sanitizer邮件列表中。
- 如何将enable-if与模板参数和参数包一起使用
- 如何将PERF_AMPLE_READ与mmap一起使用
- 如何将两个不同矢量的同一位置的两个元素组合在一起
- 如何将C++中的库和头与MinGW一起使用
- 将--whole archive链接器选项与CMake和具有其他库依赖项的库一起使用
- 为什么我不能将 rand() 与数组的大小一起使用?
- 要与"if constexpr"一起使用的编译时消息(在预处理器之后)
- 不能将复制初始化与隐式转换的多个步骤一起使用
- 将fold表达式与std::一起用于两个元组
- spdlog标头仅与外部fmt一起使用.spdlog错误:'内部':不是'fmt'
- 将 std::allocate_shared 与多态资源分配器一起使用
- 为什么常量词在重载运算符中不与 ostream 对象一起使用<<?
- 将 OpenCV 与 CMAKE 中的项目一起构建为第三方库的正确方法
- 在运行时读取 libstdc++ 版本
- 将 exprtk 与自定义类的对象一起使用
- 将 std::set 与基于键的比较器一起使用
- 将 C++ 类与 Rcpp 一起使用,从 C 或 R 修改它
- 获取指向成员std::string::size的指针无法与libc++链接,但可以与libstdc++一起使用
- 将内存清理程序与libstdc++一起使用
- 将libstdc++.so.6与应用程序一起发布