使用 std::make_shared 和虚拟继承时 valgrind 报告的未初始化值
Uninitialized value reported by valgrind when using std::make_shared and virtual inheritance
我有以下(过于简化的)示例,其中 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
通过 valgrind 使用 gcc 4.9.2 c++14 标志和 运行 编译它,我得到以下输出:
==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)
这是由于编译器在对象末尾添加的填充(注意 "spans" 8 字节的 bool)吗?如果是这样 - 如何才能使检查不失败?
您的示例是未定义的行为,因为 X 不是 POD。因此,以这种方式开始读取随机字节是非法的。要转储对象就转储对象,不要假装转储字节是一回事
无论是否是 gmock 代替您进行转储,这都是正确的。
我有以下(过于简化的)示例,其中 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
通过 valgrind 使用 gcc 4.9.2 c++14 标志和 运行 编译它,我得到以下输出:
==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)
这是由于编译器在对象末尾添加的填充(注意 "spans" 8 字节的 bool)吗?如果是这样 - 如何才能使检查不失败?
您的示例是未定义的行为,因为 X 不是 POD。因此,以这种方式开始读取随机字节是非法的。要转储对象就转储对象,不要假装转储字节是一回事
无论是否是 gmock 代替您进行转储,这都是正确的。