valgrind 在使用 std::make_shared 和虚拟继承时报告的未初始化值

Uninitialized value reported by valgrind when using std::make_shared and virtual inheritance

本文关键字:报告 继承 初始化 虚拟 shared std make valgrind      更新时间:2023-10-16

我有以下(过于简化的)例子,valgrind抱怨未初始化的内存:

struct B {
  virtual ~B() {}
};
struct BB : public virtual B {
  virtual ~BB() = default;
};
struct BBB : public virtual B {
  virtual ~BBB() {}
};
struct X : public virtual B, public virtual BBB/*, public virtual BB*/ {
  X() { a = 0.0; b = 0.0; c = false;}
  double a;
  double b;
  bool c;
};

并像这样使用它:

auto y = std::make_shared<X>();
HexDump(y.get(), sizeof(X)); // simple hexdump function - similar to gtest output - in real application this is an "uninteresting mock call" where gtest prints binary representation of an object using its size

这里的工作示例:http://coliru.stacked-crooked.com/a/91a54b697010d84b

使用 gcc 4.9.2 c++14 标志编译它并运行 valgrind,我得到以下输出:

==58887== Conditional jump or move depends on uninitialised value(s)
==58887==    at 0x93A065: __vfprintf (in /usr/lib/system/libsystem_c.dylib)
==58887==    by 0x95E2DA: __v2printf (in /usr/lib/system/libsystem_c.dylib)
==58887==    by 0x9441DC: vsprintf_l (in /usr/lib/system/libsystem_c.dylib)
==58887==    by 0x93464C: sprintf (in /usr/lib/system/libsystem_c.dylib)
==58887==    by 0x100165310: HexDump(void*, unsigned int) (in xxxx)
==58887== Use of uninitialised value of size 8
==58887==    at 0x93A69B: __ultoa (in /usr/lib/system/libsystem_c.dylib)
==58887==    by 0x93A0CC: __vfprintf (in /usr/lib/system/libsystem_c.dylib)
==58887==    by 0x95E2DA: __v2printf (in /usr/lib/system/libsystem_c.dylib)
==58887==    by 0x9441DC: vsprintf_l (in /usr/lib/system/libsystem_c.dylib)
==58887==    by 0x93464C: sprintf (in /usr/lib/system/libsystem_c.dylib)
==58887==    by 0x100165310: HexDump(void*, unsigned int) (in xxxxx) 

这是由于编译器在对象末尾添加了填充(请注意"跨越"8 个字节的布尔值)?如果是这样 - 可以做些什么来使检查不失败?

您的示例是未定义的行为,因为 X 不是 POD。因此,以这种方式开始从随机字节读取是非法的。如果要转储对象,请实际转储对象,并且不要假装转储字节是一回事。

这是真的,无论是gmock而不是你做倾倒。