0xC0000005: Ошибка определения местоположения нарушения доступа в деструкторе - PullRequest
0 голосов
/ 14 апреля 2019

У меня есть класс, предназначенный для загрузки файлов изображений в растровые изображения и хранения ссылок на эти растровые изображения.Я хочу освободить эти ресурсы в какой-то момент позже, как раз перед закрытием приложения.

Итак, мой класс (одноэлементный) сконструирован так:

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 ]

1 голос
/ 18 апреля 2019

Allegro 5 не очень хорошо работает с глобальными переменными типа синглетонов.

Вещи, которые нужно запомнить:

1) Глобальные объекты или глобальные вызовы статической инициализации происходят до вызова al_init.Это означает, что вызовы аллегро-функций внутри их конструкторов завершатся неудачей.

2) Глобальная статика переживает main и atexit.Это означает, что их деструкторы будут работать после того, как allegro обычно отключается. al_install_system перехватывает atexit для закрытия его библиотеки, если вы специально не запретите.Это означает, что вызовы функций allegro, таких как al_destroy_bitmap, будут неудачными, и segfault, если вам повезет.

Вам придется явно «выключить» ваш экземпляр ImageManager, прежде чем atexit и main выйдут ИЛИ, прежде чем вы вызовете al_uninstall_system .

0 голосов
/ 14 апреля 2019

Изменение instance на указатель, getInstance создание экземпляра и добавление явного destroyInstance вызова для удаления экземпляра до return 0 может решить проблему, поскольку у вас больше нет последовательности уничтожения / освобождения, котораянаходится вне вашего контроля после выхода из main.

...