C++ valgrind报告使用std::string读取无效

C++ valgrind报告使用std::string读取无效,c++,c++11,gcc,valgrind,C++,C++11,Gcc,Valgrind,我正在编写在raspberry pi 3上运行的代码。并且在我的日志类中出现以下错误 ==1297== Invalid read of size 8 ==1297== at 0x4865D1C: ??? (in /usr/lib/arm-linux-gnueabihf/libarmmem.so) ==1297== Address 0x4c8d45c is 100 bytes inside a block of size 107 alloc'd ==1297== at 0x4847D

我正在编写在raspberry pi 3上运行的代码。并且在我的日志类中出现以下错误

==1297== Invalid read of size 8
==1297==    at 0x4865D1C: ??? (in /usr/lib/arm-linux-gnueabihf/libarmmem.so)
==1297==  Address 0x4c8d45c is 100 bytes inside a block of size 107 alloc'd
==1297==    at 0x4847DA4: operator new(unsigned int) (vg_replace_malloc.c:328)
==1297==    by 0x49C3D9B: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::reserve(unsigned int) (in /usr/lib/arm-linux-gnueabihf/libstdc++.so.6.0.22)
==1297==    by 0x4AE65: std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > std::operator+<char, std::char_traits<char>, std::allocator<char> >(char const*, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (basic_string.tcc:1155)
==1297==    by 0xF82B5: Log::Book::addField(std::unique_ptr<Log::Entry, std::default_delete<Log::Entry> >&, unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) (LogBook.cpp:149)
==1297==    by 0xF7CCB: Log::Book::record(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, int, unsigned int, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::chrono::time_point<std::chrono::_V2::system_clock, std::chrono::duration<long long, std::ratio<1ll, 1000000000ll> > >) (LogBook.cpp:87)

更新1: 我使用带有选项的cmake进行编译。并增加了额外的选择。这些并没有解决问题

add_compile_options(-ggdb)
add_compile_options(-O1)

#Extra disable vectorization
add_compile_options(-fno-tree-vectorize)
add_compile_options(-fno-tree-loop-vectorize)
add_compile_options(-fno-tree-slp-vectorize)

更新2:
我发现另一个地方使用了字符串连接,valgrind报告了相同的错误


更新3:
一些时间和有趣的发现。 共享库libarmmem.so中发生错误。这会动态加载,因此始终位于不同的地址。使用gdb和valgrind组合在错误发生时中断。
gdb加载了具有起始地址的共享库

(gdb) info sharedlibrary
From        To          Syms Read   Shared Object Library
0x0483246c  0x04832750  Yes         /usr/local/lib/valgrind/vgpreload_core-arm-linux.so
0x04846e60  0x04850c10  Yes         /usr/local/lib/valgrind/vgpreload_memcheck-arm-linux.so
0x04863588  0x048672fc  Yes (*)     /usr/lib/arm-linux-gnueabihf/libarmmem.so
...
valgrind报告的错误

==9442== Invalid read of size 8
==9442==    at 0x4865D34: ??? (in /usr/lib/arm-linux-gnueabi/libarmmem.so)
我们从libarmmem的readelf得知.text部分从588开始。这个memcpy位于710上。此断点上的反汇编显示我们位于地址0x04863710的memcpy中。如果我们检查如下范围:0x04863588-0x04863710=188。188+588(文本的起始地址)=710。
拆解显示它发生在装配线上。vldmia是用于加载向量浮点寄存器的指令

0x04865d34 <+9764>: vldmia  r1!, {d9}
0x04865d34:vldmia r1!,{d9}

目前还没有解决方案。

最有可能的是libarmem.so中的代码已经矢量化,它意识到只有在读取完整的8字节块之后才有终止字符。这不会触发处理器异常(因为算法确保指针对齐,因此保持在同一页中),但会导致Valgrind等工具报告误报


随着时间的推移,这类问题越来越严重,使得Valgrind在实践中的作用越来越小。有关深入讨论或实际示例(或更多示例),请参见。

使用
-O1
编译并重新运行测试<代码>-O2及以上产生虚假发现。另请参见。@jww我已经在用标志-ggdb-O0-Wextra-std=c++14编译了。我想valgrind可以使用-ggdb。遗憾的是,valgrind无法区分由于操作矢量化而发生的故意越界(“合法”)和意外发生的越界。尝试禁用编译器的矢量化(是的,在O0模式下较新的编译器可能会出现此问题),并查看在
textOutput=“;”+text根据valgrind的输出。
reserve
的调用发生在它创建新的临时字符串对象时,该对象必须符合
运算符+
内的连接结果。除非堆以某种方式损坏,否则不会出现问题。该输出并不意味着在
Log::Book::addField
或字符串函数中发生错误。这意味着libarmmem.so中的某个地方发生了错误,但valgrind无法确定调用该库的函数,并且该错误涉及一个指针,该指针位于先前由
std::string
函数在
Log::Book::addField
期间分配的内存末尾附近。
==9442== Invalid read of size 8
==9442==    at 0x4865D34: ??? (in /usr/lib/arm-linux-gnueabi/libarmmem.so)
0x04865d34 <+9764>: vldmia  r1!, {d9}