2013-12-16 3 views
26

Я хочу использовать -fsanitize=memory флаг в звоне проанализировать программу вроде следующего:Использования памяти дезинфицирующее с libstdC++

#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

+0

Может быть удобным для комментариев в строке исходного кода 10, чтобы мы могли более легко связать его с сообщением об ошибке. – PeterSW

+0

Это дает аналогичную ошибку, если вы используете 'outstream o (" dum ");' вместо 'o.open (" dum ");'? – PeterSW

+0

@PeterSW такой же выпуск. – soandos

ответ

5

Там простой способ в настоящее время является создание LibC++ с memorysanitizer, а затем связать свою программу против него.

Это, как я сделал это некоторое время назад, не сумев справиться с LibC системы сборки ++: https://code.google.com/p/memory-sanitizer/source/browse/bootstrap/build_libcxx.sh

Я слышал, что были улучшения на LibC++ стороне, может быть, можно было бы построить его как обычно (с чем-то вроде CC =/path/to/clang CFLAGS = -fsanitize = memory).

+0

Как я могу это сделать? – soandos

+0

вы можете использовать libstdC++, но вам придется его исправить, а затем построить gcc специально – user3125280

+0

@ user3125280, чтобы я мог просто запустить ваш скрипт? – soandos

15

код прекрасно, конечно, но многие подобные ошибки вызывают следующее требование памяти звона в дезинфицирующем средстве:

MemorySanitizer (without a dynamic component) requires that the entire program code including libraries, (except libc/libm/libpthread, to some extent), is instrumented.

from here

cplusplus среда используется libstdC++ является unistrumented и причинами ошибки. Вы, к сожалению, следовать несколько неудобный процесс, как описано в этой ссылке, чтобы перестраивать инструментальную libstdC++ или переключиться на LibC++ (проще иш)

+0

Есть ли вероятность, что вы можете вычислить бит '../../../ libstdC++ - v3/configure'? О какой настройке он говорит? – soandos

+0

@soandos сценарий конфигурации для - подождите, что вы сделали до сих пор – user3125280

+0

это стандартная сборка для gcc (никоим образом не стандартная сборка, хотя! :)) вы создаете несколько папок вне исходного дерева и гадаете вокруг - я буду найти хороший учебник (есть один в OSDev wiki IRRC) и написать вам подробный ответ утром – user3125280

2

How can I make this work properly?

Вы можете также 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's libc++. См. Memory Sanitizer Libcxx HowTo и How to unpoison a C++ std::string? в списке рассылки Sanitizer Memory.

+0

Очень полезно в других контекстах. – soandos

Смежные вопросы