我可以让 valgrind 告诉我 _哪个_值未初始化吗?
Can I get valgrind to tell me _which_ value is uninitialized?
我在某些代码上运行了valgrind
,如下所示:
valgrind --tool=memcheck --leak-check=full --track-origins=yes ./test
它返回以下错误:
==24860== Conditional jump or move depends on uninitialised value(s)
==24860== at 0x4081AF: GG::fl(M const&, M const&) const (po.cpp:71)
==24860== by 0x405CDB: MO::fle(M const&, M const&) const (m.cpp:708)
==24860== by 0x404310: M::operator>=(M const&) const (m.cpp:384)
==24860== by 0x404336: M::operator<(M const&) const (m.cpp:386)
==24860== by 0x4021FD: main (test.cpp:62)
==24860== Uninitialised value was created by a heap allocation
==24860== at 0x4C2EBAB: malloc (vg_replace_malloc.c:299)
==24860== by 0x40653F: GODA<unsigned int>::allocate_new_block() (goda.hpp:82)
==24860== by 0x406182: GODA<unsigned int>::GODA(unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) (goda.hpp:103)
==24860== by 0x402A0E: M::init(unsigned long) (m.cpp:63)
==24860== by 0x403831: M::M(std::initializer_list<unsigned int>, MO const*) (m.cpp:248)
==24860== by 0x401B56: main (test.cpp:31)
所以第 71 行有一个错误。好的,太好了。以下是通往po.cpp
第 71 行的行(第 71 行是最后几行(:
DEG_TYPE dtk = t.ord_deg();
DEG_TYPE duk = u.ord_deg();
bool searching = dtk == duk;
NVAR_TYPE n = t.nv();
NVAR_TYPE k = 0;
for (/* */; searching and k < n; ++k) { // this is line 71
好的,那么第 71 行的哪个值未初始化?
- 当然不是
k
; - 我手动检查(="单步执行
gdb
"(t
的构造函数初始化了t.nv()
返回的值,所以肯定不是n
(实际上n
设置为6,正确的值(; searching
由dtk
和duk
确定,但我也手动检查了t
和u
的构造函数是否初始化了.ord_deg()
返回的值(实际上dtk
和duk
都设置为 3,这是正确的值(。
我在这里完全不知所措。是否有一些选项可以告诉valgrind
报告它认为未初始化的精确值?
更新
为了回答一个问题,这里是test.cpp
的第61行:
M s { 1, 0, 5, 2, 0 };
因此,它使用初始值设定项列表进行构造。下面是该构造函数:
M::M(
initializer_list<EXP_TYPE> p, const MO * ord
) {
common_init(ord);
init_e(p.size());
NVAR_TYPE i = 0;
last = 0;
for (
auto pi = p.begin();
pi != p.end();
++pi
) {
if (*pi != 0) {
e[last] = i;
e[last + 1] = *pi;
last += 2;
}
++i;
}
ord->set_data(*this);
}
下面是类中的数据,添加注释显示其初始化位置:
NVAR_TYPE n; // init_e()
EXP_TYPE * e; // common_init()
NVAR_TYPE last; // common_init()
DEG_TYPE od; // common_init(), revised in ord->set_data()
const MO * o; // common_init()
MOD * o_data; // common_init(), revised in ord->set_data()
是否有一些选项可以告诉 valgrind 报告哪个精确 它认为值未初始化?
您能做的最好的事情就是使用--track-origins=yes
(您已经在使用此选项(。Valgrind 只会告诉您未初始化值的大致位置(以 Valgrind 表示的原点(,但不会告诉您确切的变量名称。请参阅瓦尔格林德手册以获取--track-origins
:
当设置为"是"时,Memcheck会跟踪所有来源 未初始化的值。然后,当未初始化的值错误 报告,Memcheck将尝试显示值的来源。一个起源 可以是以下四个位置之一:堆块、堆栈 分配、客户端请求或其他其他来源(例如,一个 致电 BRK(。
对于源自堆块的未初始化值,Memcheck 显示 块的分配位置。对于源自的未初始化值 从堆栈分配中,Memcheck可以告诉您哪个函数 分配了值,但不超过这个值 - 通常它会显示 函数的左大括号的源位置。所以你 应仔细检查函数的所有局部变量是否为 已正确初始化。
您可以使用 gdb+vgdb+valgrind 在 valgrind 下调试程序。
然后,当 valgrind 因上面报告的错误而停止时,您可以检查 您有兴趣使用监视器请求的变量的定义性 "xb"或"get_vbits"通过询问变量的地址,然后检查 变量大小的 VBIT。
例如:
p &searching
=> 0xabcdef
monitor xb 0xabcdef 1
=> will show you the value of searching and the related vbits.
有关更多详细信息,请参阅"使用 Valgrind gdbserver 和 GDB 调试程序"http://www.valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver 和"内存检查监视器命令"http://www.valgrind.org/docs/manual/mc-manual.html#mc-manual.monitor-commands
来自瓦尔格林德文档,
4.2.2. 使用未初始化的值
...未初始化数据的来源往往是:
- 尚未初始化的过程中的局部变量,如上例所示。
-堆块的内容(使用 malloc、new 或类似函数分配(在您(或构造函数(在那里编写内容之前。
你有:
==24860== Uninitialised value was created by a heap allocation
==24860== at 0x4C2EBAB: malloc (vg_replace_malloc.c:299)
==24860== by 0x40653F: GODA<unsigned int>::allocate_new_block() (goda.hpp:82)
因此,GODA<unsigned int>::allocate_new_block()
使用的malloc
很可能导致了此错误。
您可以使用 clang-tidy 作为查找未初始化变量的替代方法。 QtCreator 4.7完全集成了clang-tidy,在调试窗格中选择"Clang-Tidy and Clazy",按运行,选择要测试的文件。
你需要了解memcheck是如何工作的。为了避免生成过多的错误,未初始化的值在对代码产生可能的影响之前不会被标记。未初始化的信息由赋值传播。
// if ord_deg returns something that is uninitialized, dtk and/or duk will be
// flagged internally as uninitialized but no error issued
DEG_TYPE dtk = t.ord_deg();
DEG_TYPE duk = u.ord_deg();
// again transitively if either dtk or duk is flagged as uninitialized then
// searching will be flagged as uninitialized, and again no error issued
bool searching = dtk == duk;
// if nv() returns something that is uninitialized, n will be
// flagged internally as unintialized
NVAR_TYPE n = t.nv();
// k is flagged as initialized
NVAR_TYPE k = 0;
// OK now the values of searching and n affect your code flow
// if either is uninitialized then memcheck will issue an error
for (/* */; searching and k < n; ++k) { // this is line 71
您正在查看错误的堆栈跟踪。
Valgrind 告诉您未初始化的值是由堆分配创建的:
==24860== Uninitialised value was created by a heap allocation
==24860== at 0x4C2EBAB: malloc (vg_replace_malloc.c:299)
==24860== by 0x40653F: GODA<unsigned int>::allocate_new_block() (goda.hpp:82)
==24860== by 0x406182: GODA<unsigned int>::GODA(unsigned long, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&, bool) (goda.hpp:103)
==24860== by 0x402A0E: M::init(unsigned long) (m.cpp:63)
==24860== by 0x403831: M::M(std::initializer_list<unsigned int>, MO const*) (m.cpp:248)
==24860== by 0x401B56: main (test.cpp:31)
您可以从第三方库代码中省略几个顶级堆栈帧,因为错误不太可能出现在第三方代码中。您应该更仔细地查看此堆栈帧,它似乎是您的代码:
==24860== by 0x402A0E: M::init(unsigned long) (m.cpp:63)
最有可能未初始化的变量应该在代码行m.cpp:63
。
- 是否可以初始化不可复制类型的成员变量(或基类)
- C++使用整数的压缩数组初始化对象
- C++初始化基类
- 多成员Constexpr结构初始化
- 我可以让 valgrind 告诉我 _哪个_值未初始化吗?
- 哪个函数负责C++全局范围内的类对象初始化?
- 初始化时 num 的哪个值会给这个嵌套循环一个"true"输出?
- 未初始化的变量整数'A'哪个内存部分占用内存?
- 查找初始化列表中的哪个成员抛出了例外
- C++使用初始化列表委派构造函数.哪个初始化发生
- 在DirectShow管道中,哪个阶段最适合初始化资源
- C++:哪个先被调用/初始化?类构造函数或其成员变量的构造函数
- 在类嵌套静态常量成员变量初始化 Clang vs GCC 哪个编译器是正确的
- 何时在C++中使用哪个数据成员初始化
- 使用表达式的结果初始化对象时使用哪个构造函数
- 哪个函数用于初始化静态类成员
- 哪个"value"具有非初始化值?
- 语句初始化属于哪个类别
- 我在哪个时区初始化QDateTime ?
- 静态变量的哪个初始化是正确的