我有一个用于将图像文件加载到位图并保留对这些位图的引用的类。我想稍后再分配这些资源,就像关闭应用程序之前一样。
所以我的班级(单身)设计如下:
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方法:
编辑:
我的getInstance()
方法是:
ImageManager &ImageManager::getInstance()
{
static ImageManager instance;
return instance;
}
编辑2:
确切错误是0xC0000005: Access violation reading location 0xDDDDDDF1.
答案 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之后,不再具有无法控制的销毁/解除分配顺序。