调用成员方法时会丢失此指针
this pointer is lost when calling a member method
我在Fedora 17 x86_64机器上使用64位g++4.7.0编译程序时遇到了一个奇怪的问题(同样的程序在32位Fedora上运行良好)。
这个程序太复杂了,我想不出一个简单的方法来生成一个小代码示例。但从下面的gdb记录中,您可以看到问题所在。
Program received signal SIGSEGV, Segmentation fault.
0x000000000042a4b0 in boost::shared_ptr<cppPNML::details::ddObj>::operator!(this=0x100000007)
at /usr/include/boost/smart_ptr/detail/operator_bool.hpp:55
55 return px == 0;
Missing separate debuginfos, use: debuginfo-install gnome-keyring-3.4.1-3.fc17.x86_64
(gdb) bt
#0 0x000000000042a4b0 in boost::shared_ptr<cppPNML::details::ddObj>::operator! (this=0x100000007)
at /usr/include/boost/smart_ptr/detail/operator_bool.hpp:55
#1 0x00000000004202a5 in cppPNML::pnNode::getBBox (this=0xffffffff) at cpp_pnml.cpp:131
#2 0x000000000040eca4 in draw_page (g=..., painter=...) at pnml2pdf.cpp:178
#3 0x000000000040e3b9 in main (argc=2, argv=0x7fffffffe188) at pnml2pdf.cpp:106
(gdb) up
#1 0x00000000004202a5 in cppPNML::pnNode::getBBox (this=0xffffffff) at cpp_pnml.cpp:131
131 if(!p_) return pair<double, double>(0,0);
(gdb) up
#2 0x000000000040eca4 in draw_page (g=..., painter=...) at pnml2pdf.cpp:178
178 boost::tie(w, h) = node.getBBox();
(gdb) p node
$1 = {<cppPNML::pnObj> = {_vptr.pnObj = 0x79a490, p_ = {px = 0x7c40a0, pn = {pi_ = 0x7c4170}}}, <No data fields>}
(gdb) l
173 QRectF bound(0,0,0,0);
174
175 // nodes
176 for(pnNode node = g.front<pnNode>(); node.valid(); node = node.next()) {
177 double h, w, x, y, wa, ha, xa, ya, angle;
178 boost::tie(w, h) = node.getBBox();
179 angle = atan2(h, w);
180 boost::tie(x, y) = node.getPosition();
181 wa = 0; ha = 0; xa = 0; ya = 0;
182
(gdb)
正在调试的程序是一个图形打印程序(pnml2pdf),它使用QT4将图形绘制为pdf。对象节点属于pnNode类,它是由我自己的图形数据结构库定义的(相当复杂,https://github.com/wsong83/cppPNML)。它显示了一个SEG错误,其中智能指针未初始化。通过回溯,您可以看到node.getBBox()的this指针是无效的。然而,从上级打印节点显示该节点实际上是可以的
我在这里完全糊涂了。
有人有线索或需要更多的代码段吗?提前感谢!
更新:多亏了@atzz的建议,我现在确信在成员方法getBBox()中计算该指针产生了错误的地址。该问题不是由任何源代码错误引起的(直接链接对象文件将消除段错误),而是由64位静态库生成命令"ar"引起的(因为pnNode的定义是在静态库而不是对象文件中定义的)。现在看来,静态库是错误的,并导致了错误的计算。
还在挖。。。如果有人仍然有兴趣知道,将更新结果。
-
这是优化版本还是调试版本?在我看来,它应该在176线而不是178线上失败。
-
你确定循环是对的吗?看起来你快要结束了。我怀疑
node.valid()
的实现对于循环测试来说要么没有做正确的事情,要么是错误的事情。
值0xffffffff
看起来像一个std::iterator
end()
值,所以我认为你要么需要根据它来测试你的循环,要么确保pnObj::valid() const { return p_ != NULL && p_ != 0xffffffff; }
此外,您实现next()
的方式看起来也是错误的。创建迭代器,搜索字符串ID,然后在迭代器上调用next()
?
- 如果基类包含双指针成员,则派生类的构造函数
- 从私有成员变量的成员方法返回unique_ptr
- 如何将类成员方法的参数列表自动填充写入可变参数?
- C++正确的指针成员初始化
- 是否可以使用智能指针成员设置具有另一个结构的结构?
- 如何使用接口指针调用方法,该指针是其具体类的一部分,而不是接口的一部分
- 为什么 operator() 处的指针成员不起作用?
- 从类C++外部调用指向成员方法的成员指针
- C++:释放动态数组(结构成员)和指向此结构的指针的方法
- 指向 objc 类成员方法的函数指针,用于C++
- 通过指针从for_each循环中访问成员方法
- 调用成员方法时会丢失此指针
- 从成员函数指针获取方法的返回类型
- 使用C++ 11 中的模板类型的成员函数指针创建方法参数
- 从另一个方法调用成员方法指针
- 初始化智能指针成员变量的正确方法是什么
- 非常量指针成员上的C++常量方法
- 类型推断失败,指针指向成员方法
- C++编译器是为所有成员方法生成指针"this"还是仅为引用成员的方法生成指针?
- 静态成员方法应该返回什么类型的指针?