Я хочу использовать -fsanitize=memory
флаг в Clang для анализа программы, как показано ниже:
#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:
MemorySanitizer (без динамического компонента) требует, чтобы вся программа
код, включающий библиотеки, (за исключением libc / libm / libpthread, в некоторой степени), инструментирован.
Среда выполнения cplusplus, которую вы используете libstdc ++, не распространяется и вызывает ошибки. К сожалению, вам придется следовать несколько сложному процессу, как описано в этой ссылке, чтобы перестроить инструментированный libstdc ++ или перейти на libc ++ (проще-иш)
В настоящее время проще всего построить libc ++ с помощью memorysanitizer, а затем связать вашу программу с ним.
Вот как я это сделал некоторое время назад, не справившись с системой сборки 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 ++ Runtime. Они также рекомендуют использовать LLVM libc++
с целью. Увидеть Дезинфицирующее средство для памяти Libcxx HowTo а также Как отменить удаление C ++ std :: string? в списке рассылки Memory Sanitizer.