0xC0000005:析构函数中的访问冲突读取位置错误

时间:2019-04-14 04:28:20

标签: pointers c++14 allegro5

我有一个用于将图像文件加载到位图并保留对这些位图的引用的类。我想稍后再分配这些资源,就像关闭应用程序之前一样。

所以我的班级(单身)设计如下:

class ImageManager
{
public:
   static ImageManager &getInstance();
   ImageManager(ImageManager const&) = delete;
   void operator=(ImageManager const&) = delete;
   void loagImage(char *location);
   ~ImageManager();
private:
   ImageManager();
   ALLEGRO_BITMAP *image = nullptr;
}

构造函数中实际上没有什么东西。只需加载与处理位图有关的加载项。没有创建原始指针。

loadImage()的实现如下:

void ImageManager::loadImage(char *location)
{
    if(!location)
    {
       throw std::invalid_argument("Location cannot be null.");
    }
    image = al_load_bitmap(location);
}

析构函数的定义类似

ImageManager::~ImageManager()
{
   if(image)
   {
       al_destroy_bitmap(image); // Here I get the access violation exception.
   }
}

main.cpp中使用此类的方式如下:

int main(int argc, char *args[])
{
    ImageManager &imgManager = ImageManager::getInstance();
    imgManager.loadImage("valid/location");

    return 0;
}

如果我在加载位图的同一函数中调用al_destroy_bitmap(),则没有错误。仅当我尝试在析构函数中调用它时,这种情况才会发生。

我在Windows 10上使用VS17。我在同一个主题上看到了许多问题,但是我无法使用那里的答案找出错误。如果需要,我还将在此处链接到这两种Allegro方法:

  1. al_load_bitmap()
  2. al_destroy_bitmap()

编辑:

我的getInstance()方法是:

ImageManager &ImageManager::getInstance()
{
    static ImageManager instance;
    return instance;
}

编辑2:

确切错误是0xC0000005: Access violation reading location 0xDDDDDDF1.

2 个答案:

答案 0 :(得分:1)

Allegro 5不能与单例之类的全局变量配合使用。

要记住的事情:

1)全局对象或对静态初始化的全局调用在调用al_init之前发生。这意味着在其构造函数内部对allegro函数的调用将失败。

2)全局静态变量胜过main和atexit。这意味着它们的析构函数将在Allegro通常关闭后运行。 al_install_system会钩挂atexit来关闭它的库,除非您明确告知不要这样做。这意味着,如果幸运的话,对al_destroy_bitmap之类的Allegro函数的调用将失败并出现段错误。

在atexit和main退出之前,或者在调用al_uninstall_system之前,您必须明确“关闭” ImageManager实例。

答案 1 :(得分:0)

instance更改为指针,使getInstance创建一个实例,并在destroyInstance之前添加一个明确的return 0调用以删除该实例可能会解决此问题,因为您没有退出main之后,不再具有无法控制的销毁/解除分配顺序。