【问题标题】:Segmentation fault when calling a virtual function from an object of the base class从基类的对象调用虚函数时出现分段错误
【发布时间】: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


【解决方案1】:

我会尝试动态转换为 C 指针:

if ((*it)) {
    printf("*it is not null\n");
    dynamic_cast<C*>(*it)->foo();
    printf("Called B::foo()\n");
}

因为没有其他明显的段错误原因。

【讨论】:

    猜你喜欢
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-08
    相关资源
    最近更新 更多