0xC0000005:析构函数中的访问冲突读取位置错误
0xC0000005: Access violation reading location error in destructor
我有一个 class 用于将图像文件加载到位图并保留对这些位图的引用。我想在稍后的某个时候释放这些资源,比如在关闭应用程序之前。
所以我的class(是单例)设计如下:
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.
}
}
class 在 main.cpp
中的使用方式如下:
int main(int argc, char *args[])
{
ImageManager &imgManager = ImageManager::getInstance();
imgManager.loadImage("valid/location");
return 0;
}
如果我在加载位图的同一函数中调用 al_destroy_bitmap()
,则没有错误。只有当我尝试在析构函数中调用它时才会发生。
我正在 Windows 10 使用 VS17。我看到了很多关于同一主题的问题,但我无法使用那里的答案找出错误。我也会 link 这里的两种快板方法,以备您需要:
编辑:
我的getInstance()
方法是:
ImageManager &ImageManager::getInstance()
{
static ImageManager instance;
return instance;
}
编辑 2:
确切的错误是 0xC0000005: Access violation reading location 0xDDDDDDF1.
将 instance
更改为指针,让 getInstance
创建实例,并在 return 0
之前添加显式 destroyInstance
调用以删除实例可能会解决问题,因为退出 main 后,您不再有不受控制的 destruction/deallocation 序列。
Allegro 5 不能很好地处理像单例这样的全局变量。
要记住的事情:
1) 全局对象或对静态初始化的全局调用发生在调用 al_init
之前。这意味着在其构造函数中调用 allegro 函数将失败。
2) 全局静态比 main 和 atexit 更有效。这意味着它们的析构函数将在 allegro 通常关闭后 运行。 al_install_system 挂钩 atexit 以关闭它的库,除非你明确告诉它不要这样做。这意味着调用 al_destroy_bitmap
之类的 allegro 函数将失败,如果幸运的话会出现段错误。
您必须在 atexit 和 main 退出之前或调用 al_uninstall_system.
之前明确 'shutdown' 您的 ImageManager 实例
我有一个 class 用于将图像文件加载到位图并保留对这些位图的引用。我想在稍后的某个时候释放这些资源,比如在关闭应用程序之前。
所以我的class(是单例)设计如下:
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.
}
}
class 在 main.cpp
中的使用方式如下:
int main(int argc, char *args[])
{
ImageManager &imgManager = ImageManager::getInstance();
imgManager.loadImage("valid/location");
return 0;
}
如果我在加载位图的同一函数中调用 al_destroy_bitmap()
,则没有错误。只有当我尝试在析构函数中调用它时才会发生。
我正在 Windows 10 使用 VS17。我看到了很多关于同一主题的问题,但我无法使用那里的答案找出错误。我也会 link 这里的两种快板方法,以备您需要:
编辑:
我的getInstance()
方法是:
ImageManager &ImageManager::getInstance()
{
static ImageManager instance;
return instance;
}
编辑 2:
确切的错误是 0xC0000005: Access violation reading location 0xDDDDDDF1.
将 instance
更改为指针,让 getInstance
创建实例,并在 return 0
之前添加显式 destroyInstance
调用以删除实例可能会解决问题,因为退出 main 后,您不再有不受控制的 destruction/deallocation 序列。
Allegro 5 不能很好地处理像单例这样的全局变量。
要记住的事情:
1) 全局对象或对静态初始化的全局调用发生在调用 al_init
之前。这意味着在其构造函数中调用 allegro 函数将失败。
2) 全局静态比 main 和 atexit 更有效。这意味着它们的析构函数将在 allegro 通常关闭后 运行。 al_install_system 挂钩 atexit 以关闭它的库,除非你明确告诉它不要这样做。这意味着调用 al_destroy_bitmap
之类的 allegro 函数将失败,如果幸运的话会出现段错误。
您必须在 atexit 和 main 退出之前或调用 al_uninstall_system.
之前明确 'shutdown' 您的 ImageManager 实例