【问题标题】:Why does calling a method on a shared_ptr in a vector throw a runtime exception?为什么在向量中的 shared_ptr 上调用方法会引发运行时异常?
【发布时间】:2016-11-05 06:34:40
【问题描述】:

为什么下面的代码会抛出

Exception thrown at 0x53A5C6DC (nvoglv32.dll) in RenderEngine.exe: 0xC0000005: Access violation reading location 0x0002B174.

在运行时,什么是好的解决方案?

std::vector<std::shared_ptr<Static>> statics;

void drawStatics() {
    for (std::shared_ptr<Static> stat: statics) {
        Static *statptr = stat.get();

        statptr->Draw(); //This is what triggers the runtime exception.
    }
}

void addStatic(Mesh &mesh, Texture &texture, Transform transform) {
    statics.push_back(
        std::make_shared<Static>(
            mesh,
            texture,
            transform,
            shader,
            camera
        ));
}

int main() {
    addStatic(playerMesh, playerTexture, platformTransform);
    drawStatics();

    return 0;
}

静态头文件如下:

#pragma once

#include "mesh.h"
#include "texture.h"
#include "transform.h"
#include "camera.h"
#include "shader.h"

class Static {
public:
    Static(Mesh &mesh, Texture &texture, Transform &transform, Shader &shader, Camera &camera);
    ~Static();

    void Draw();

private:
    Mesh *mesh;
    Texture *texture;
    Transform *transform;
    Shader *shader;
    Camera *camera;
};

在静态源文件中 Draw() 实现为:

void Static::Draw() {
    texture->Bind(0);
    shader->Update(*transform, *camera);
    mesh->Draw();
}

以及所要求的静态构造函数和解构函数:

Static::Static(Mesh &mesh, Texture &texture, Transform &transform, Shader &shader, Camera &camera)
    :mesh(&mesh), texture(&texture), transform(&transform), shader(&shader), camera(&camera)
{}

Static::~Static() {}

编辑: 如果这很重要,我正在使用 Visual Studio。

【问题讨论】:

  • shared_ptr 似乎没有正确初始化。
  • 你为什么要get()指针?没必要。
  • @πάνταῥεῖ 我将包括将 shared_ptr 添加到向量的方法。
  • @Llewv 更好的是,为我们提供minimal reproducible example,它可以重现问题。
  • 现在是Static 成员、构造函数和Draw 方法。

标签: c++ shared-ptr runtimeexception


【解决方案1】:

这就是你在整个代码中抛出指针和引用而不考虑生命周期的结果。

void addStatic(Mesh &mesh, Texture &texture, Transform transform) {

您按值获取Transform,这意味着它会被复制,因此该函数有它自己的实例。

 std::make_shared<Static>(
            mesh,
            texture,
            transform,
            shader,
            camera
        ));

Static::Static(Mesh &mesh, Texture &texture, Transform &transform, Shader &shader, Camera &camera)
    :mesh(&mesh), texture(&texture), transform(&transform), shader(&shader), camera(&camera)
{}

您将一个对局部变量的引用传递给Static::Static,获取它的指针并存储该指针。 addStatic 返回,本地的 Transform 被破坏,你最终得到一个悬空指针,指向你的 Transform* 中的一块空闲内存。

不确定您的其他指针,但您将所有内容都作为参考,因此请检查,当它们将被销毁时,其他指针也可能指向空闲空间。


顺便说一句:

Static *statptr = stat.get();
statptr->Draw();

您不需要get() 指针。 C++ 的智能指针(几乎)表现得像原始指针,所以

stat->Draw();

有效。

【讨论】:

  • 谢谢,我仍然习惯于处理指针,因为我已经习惯了 Java。
猜你喜欢
  • 2012-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-04
  • 2016-06-15
  • 1970-01-01
  • 2016-01-24
  • 1970-01-01
相关资源
最近更新 更多