【发布时间】:2015-05-09 11:43:25
【问题描述】:
尝试从对象调用虚函数时,我遇到了分段错误(请参阅帖子底部的调试器报告)。我已经阅读了我找到的每一个 stackoverflow 答案和每一篇网络文章,但似乎没有一个能够解决或解决手头的问题。
以下面的代码(模仿我的代码结构)为例:
类声明。
class A{
public:
A();
virtual void foo();
};
class B : A{
public:
B();
};
class C : B{
public:
C();
virtual void foo();
};
类实现。
B::B() : A(){
}
C::C() : B(){
}
void A::foo(){
}
void C::foo(){
// Code specific to class C
}
发生段错误的函数(向量声明在这里供参考,并在其他地方声明和使用)。
std::vector<B*>* vec = new std::vector<B*>();
void bar(){
if(vec){
for(auto it = vec->begin(); it != vec->end(); it++){
if((*it)){
printf("*it is not null\n");
(*it)->foo();
printf("Called B::foo()\n");
}
}
}
}
段错误发生在从*it 调用foo() 时。
我已经验证*it 不为空,因为正在打印第一条调试消息并且vec 确实包含C 类型的元素。我在 C::foo() 中添加了调试消息,所以我会知道它何时被调用,但它永远不会调用,并且bar() 中的第二条调试消息不会打印。
什么可能导致段错误?
LLDB 错误报告:
进程 24504 已停止 *线程#1:tid = 0x19134f,0x0000000000000000,队列='com.apple.main-thread',停止原因= EXC_BAD_ACCESS(代码= 1, 地址=0x0)
第 0 帧:0x0000000000000000
错误:0x0 内存读取失败
编辑: 测试用例:https://gist.github.com/SamTebbs33/5fe56879dc6a423842ad
由于某种原因,上述测试用例有效,尽管它反映了我的代码结构。
编辑 2: 使用 Valgrind 后得到如下报告:https://gist.github.com/SamTebbs33/469eefda95a5006abf64
【问题讨论】:
-
你能构造一个minimal test-case吗? (FWIW 这是一个似乎可以正常工作的示例:ideone.com/p4WZO3.)
-
如果您可以发布问题的最小可编译示例(我们可以剪切和粘贴的完整源文件),将会更有帮助。如果你这样做,我希望问题会变得很明显。
-
如果可用,请使用valgrind。
-
您的测试用例完全没有失败。是什么让你如此确定只是因为它是非空的,它仍然是一个 valid 对象指针?据我们所知(因为我们没有您的 真实 代码,也没有可重现的传真),您在该向量中有一个悬空指针、一个损坏的向量、对象本身可能已损坏等等。你通过 Valgrind 运行这个?
-
@SamTebbs33 这是意料之中的。问题出在代码中的其他地方。将代码重构为更小的、可测试的块,并且在容器中存储多态对象时使用 unique_ptr、shared_ptr 或 reference_wrapper。没有理由使用原始指针。
标签: c++ segmentation-fault lldb virtual-functions