当前位置: 首页 > 知识库问答 >
问题:

clang memory sanitizer报告未初始化值的使用

淳于凯
2023-03-14

此代码取自IncludeOS github页面。我对它进行了一些修改,使其在编译时不需要其他头文件 find函数有点过于冗长,所以我想简化它。但修改后,代码的行为与我预期的不同。

这里有一个简短的解释。此代码用于解析HTTP头。标题字段是名称-值对。它表示为向量

main函数中,四个元素附加到字段中。六个不应该在字段中找到。但是has_field返回true。

我试图用gdb跟踪错误。但我迷失在产出的海洋中。我确实发现了一条有趣的消息。

Std::__uninitialized_copy

{第一=

我使用了clang消毒剂来找出问题所在。只有内存消毒剂显示有趣的报告。运行,

clang-std=c 17-O1-fsanizize=memory-fsanizize memory track origins-fno省略帧指针main。抄送

a.out报告,

未初始化的值是通过在函数“\u ZNSt4pairINSt7\u cx1112basic\u stringIcSt11char\u traitsIcESaIcEEES5\u EC2IRA6\u KcRA2\u S8\u lb1eeot\u OT0\u”的堆栈框架中分配“ref.tmp”创建的。

但是,当优化级别设置为-O3时,不会显示任何内容。

#include <algorithm>
#include <iostream>
#include <vector>
#include <experimental/string_view>

using Headers = std::vector<std::pair<std::string, std::string>>;
using string_view = std::experimental::string_view;

Headers::const_iterator find(Headers fields, const string_view field) {
  if (field.empty()) return fields.cend();
  //-----------------------------------
  return
    std::find_if(fields.cbegin(), fields.cend(), [field](const auto _) {
      return std::equal(_.first.cbegin(), _.first.cend(), field.cbegin(), field.cend(), 
        [](const auto a, const auto b) { return std::tolower(a) == std::tolower(b); }); 
    }); 
}

bool has_field(Headers fields, const string_view field)
{
  return find(fields, field) != fields.cend();
}

int main()
{
  Headers fields;
  fields.emplace_back("one", "1");
  fields.emplace_back("two", "2");
  fields.emplace_back("three", "3");
  fields.emplace_back("four", "4");

  std::string s = "six";
  if (has_field(fields, s)) 
    std::cout << s << " is in " << "fields" << std::endl;

  return 0;
}

共有2个答案

督辉
2023-03-14

似乎Clang的内存清理器也希望检测外部库(libstrdc),否则很可能出现误报。

https://clang.llvm.org/docs/MemorySanitizer.html#id11

MemorySinitizer要求插入所有程序代码。这还包括程序所依赖的任何库,甚至libc

因此valgrind对于未初始化的值检测似乎仍然是最实用的(尽管很慢)。

况明贤
2023-03-14

很可能是误报。llvm带有符号二进制,它允许消毒剂输出行号。我用这个最小的例子再现了您的错误:

  1 #include <iostream>
  2 #include <vector>
  3 
  4 using Headers = std::vector<int>;
  5 
  6 bool a(Headers fields) {
  7     return true;
  8 }   
  9 
 10 bool b(Headers fields)
 11 {
 12   return a(fields);
 13 }
 14 
 15 int main()
 16 { 
 17   Headers fields;
 18   
 19   if (b(fields)) {
 20     std::cout << std::endl;
 21   }
 22 
 23   return 0;
 24 }

在这两种情况下,堆栈跟踪声明std::endl是罪魁祸首。要发生错误,必须发生以下神奇的事情:

  • 输出std::endl
  • 有两个函数调用

如果我声明a通过引用获取字段,错误就会消失;b不能这么说。所有这些都让我相信这是荒谬的和误报。作为参考,以下是带有行号的消毒剂输出:

Uninitialized bytes in __interceptor_memcmp at offset 192 inside [0x7fff18347610, 256)
==5724==WARNING: MemorySanitizer: use-of-uninitialized-value
    #0 0x7f8f663d94ab in std::ctype<char>::_M_widen_init() const (/lib64/libstdc++.so.6+0xb74ab)
    #1 0x7f8f66435d17 in std::basic_ostream<char, std::char_traits<char> >& std::endl<char, std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&) (/lib64/libstdc++.so.6+0x113d17)
    #2 0x4912ff in main test.cpp:20:15
    #3 0x7f8f65415889 in __libc_start_main (/lib64/libc.so.6+0x20889)
    #4 0x41a9b9 in _start (a.out+0x41a9b9)

  Uninitialized value was created by an allocation of 'ref.tmp' in the stack frame of function '_ZNSt6vectorIiSaIiEEC2ERKS1_'
    #0 0x491360 in std::vector<int, std::allocator<int> >::vector(std::vector<int, std::allocator<int> > const&) /usr/bin/../lib/gcc/x86_64-redhat-linux/7/../../../../include/c++/7/bits/stl_vector.h:329

SUMMARY: MemorySanitizer: use-of-uninitialized-value (/lib64/libstdc++.so.6+0xb74ab) in std::ctype<char>::_M_widen_init() const
Exiting
 类似资料:
  • 执行以下用clang-9-fsanitize=内存编译的程序时,我收到未初始化值的使用警告: 这是我得到的警告: 这是假阳性还是有什么深层原因? 谢谢

  • 据我所知,在Java11中,这两个操作可以在一行中完成,不是吗?

  • 以下是我的配置 java版本“1.8.0_101”java(TM)SE运行时环境(构建1.8.0_101-b13)java热点(TM)64位服务器虚拟机(构建25.101-b13,混合模式) 使用Apache http客户端v4.4调用Restful服务,服务URL具有有效的证书(SHA2) 我们使用apache http客户端调用服务。下面是代码 服务调用是间歇性失败的,有一个批处理过程在一个循

  • 我正在尝试运行一个Spring项目。pom.xml: 结果是这样的: 2017-08-17 01:11:01.405信息9156---[restartedMain]org.ocp.TestruleemallApplication:在桌面上启动TestruleemallApplication-PL25CTR,PID 9156(C:\Users\Ilias\DesktoP\TestRuleEmall\

  • 本文向大家介绍tensorflow 初始化未初始化的变量实例,包括了tensorflow 初始化未初始化的变量实例的使用技巧和注意事项,需要的朋友参考一下 今日在Stack Overflow上看到一个问如何只初始化未初始化的变量,有人提供了一个函数,特地粘贴过来共大家品鉴: 通过tf.global_variables()返回一个全局变量的列表global_vars, 然后以python列表解析式的

  • 考虑以下代码 VS2013编译器发出以下警告: 警告C4351:新行为:数组“B::member”的元素将默认初始化1 这里有记载 使用C 11,并应用“默认初始化”的概念,意味着B. part的元素将不会被初始化。 但我认为,成员{}应该执行值初始化,而不是默认初始化。VS2013编译器是否损坏? 8.5美元/6 默认初始化类型为T的对象意味着:-如果T是(可能是cv限定的)类类型(第9条),则