【问题标题】:Read Access Violation on Virtual Function对虚拟功能的读取访问冲突
【发布时间】:2021-10-09 21:57:54
【问题描述】:

这是我的程序的简化版本。

#include <iostream>
#include <vector>
class Base
{
public:
    Base()
    {

    }

    void virtual update()
    {
        std::cout << "no update function\n";
    }
    void virtual draw()
    {
        std::cout << "no draw function\n";
    }
};

class Derived : public Base
{
public:
    Derived();
    void draw() override;
    void update() override;
};

Derived::Derived()
{

}

void Derived::draw()
{
    std::cout << "draw";
}

void Derived::update()
{
    std::cout << "update";
}

class Caller
{
public:
    Caller();

    void update();
    void draw();

    void reg_obj(Base* obj);
private:
    std::vector<std::shared_ptr<Base>> all_objects;
};

Caller::Caller()
{
    Derived derived_class{};
    reg_obj(&derived_class);
}

void Caller::update()
{
    for (int i = 0; i < all_objects.size(); i++)
    {
        all_objects[i]->update();
    }
}

void Caller::draw()
{
    for (int i = 0; i < all_objects.size(); i++)
    {
        all_objects[i]->draw();
    }
}

void Caller::reg_obj(Base* obj)
{
    all_objects.push_back(std::shared_ptr<Base>{obj});
}

int main()
{
    Caller caller{};

    while (true)
    {
        caller.update();
        caller.draw();
    }
}

此代码有效,但是当它在我的完整程序中位于 caller.update();caller.draw(); 之间时,内存中的 __vfptr 值不会保持不变。当接近caller.draw() 时,__vfptr 值在调试器中的每一步都会发生变化。我不确定如何诊断 __vfptr 中的内存损坏,因为它不是我编写的程序,而是 C++ 标准的一部分。任何帮助表示赞赏。不,我无法制作可复制的版本。我不知道为什么。我确实努力让它可重现。

https://youtu.be/yd-76qDa7xc https://github.com/Sage-King/Alienor

【问题讨论】:

  • 从您在此处显示的内容看来,all_objects 数组可能已损坏,可能是由于对相邻变量的超出范围写入。
  • 0xFFFFFFFFFFFFFFFF-1。地址 0 附近的访问冲突通常意味着正在访问 NULL 指针。仔细检查您的对象指针是否有效。特别是因为您声称在进行不同的方法调用时,vtables 的显示方式不同。您的Alienor 对象是从哪里创建和使用的,它的all_objects 是如何填充的?请提供minimal reproducible example
  • 为什么是inline:inline static unsigned int ID_Factory = 0;?我从未将inline 与变量一起使用。
  • @RemyLebeau 我在另一个项目中重新创建了这个问题,它工作正常。我应该把我的整个代码库(或克隆链接)?我不知道如何在保留我已经完成的所有工作的同时制作一个最小的示例。
  • @ThomasMatthews 这是我可以在头文件中定义变量的唯一方法。说实话,我自己也不是很明白。

标签: c++ inheritance polymorphism virtual-functions


【解决方案1】:

Remy Lebeau 的解决方案: Derived derived_class{}; reg_obj(&amp;derived_class); 在您的其余代码中导致未定义的行为。您正在存储一个指向随后被销毁的本地对象的指针,在all_objects 向量中留下一个悬空指针。您对all_objects 元素的所有方法调用都作用于无效内存。要解决此问题,请将void reg_obj() 更改为采用shared_ptr&lt;Base&gt; 并将其按原样存储,然后更改Caller() 以使用std::make_shared() 创建Derived 对象,如下所示:void Caller::reg_obj(std::shared_ptr&lt;Base&gt; obj) { all_objects.push_back(obj); } Caller::Caller() { reg_obj(std::make_shared&lt;Derived&gt;()); }

【讨论】:

    猜你喜欢
    • 2016-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-17
    • 2019-05-25
    • 1970-01-01
    相关资源
    最近更新 更多