Проблемы с освобождением данных изображения из stb_image в классе-оболочке

Я пишу класс изображения для проекта, используя необработанные данные из stb_image. В деструкторе этого класса я освобождаю указатель на данные изображения, чтобы избежать утечек памяти. Однако, когда вызывается деструктор и данные освобождаются, я получаю нарушение прав доступа.

Заголовок изображения:

class Image {
    unsigned char* pixelData;
    public:
        int nCols, nRows, nChannels;
        Image(const char* filepath);
        Image(unsigned char* data, int nCols, int nRows, int nChannels);
        Image();
        ~Image();
        Image getBlock(int startX, int startY, int blockSize);
        std::vector<unsigned char> getPixel(int x, int y);
        void writeImage(const char* filepath);

};

Конструктор и деструктор изображения:

#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION

#include "stb_image.h"
#include "stb_image_write.h"
#include "image.hpp"

Image::Image(const char* filepath) {
    pixelData = stbi_load(filepath, &nCols, &nRows, &nChannels, 0);
    assert(nCols > 0 && nRows > 0 && nChannels > 0);
    std::cout << "Image width: " << nCols << "\nImage height: " << nRows << "\nNumber of channels: " << nChannels << "\n";
}

Image::~Image() {
    stbi_image_free(this->pixelData);
}

Минимальный воспроизводимый пример:

int main() {
    Image image;
    image = Image("./textures/fire.jpg");
}

Ваш класс Image нельзя безопасно скопировать или назначить. Пожалуйста, опубликуйте минимальный воспроизводимый пример , который показывает, как вы используете этот класс. Например int main() { Image im("somefile");; ... Image im2 = im; } -- Вот этот код вызовет проблемы. Прочтите правило 3 и перейдите в раздел «Управление ресурсами» по этой ссылке.

PaulMcKenzie 10.12.2020 23:24

Также поставьте точку останова в деструкторе. Не удивляйтесь, если он будет вызываться несколько раз, где каждый раз pixelData будет одним и тем же значением указателя. Если это произойдет, то я склонен закрыть этот вопрос как дубликат правила 3-х ссылок.

PaulMcKenzie 10.12.2020 23:32

Я попытался поставить точку останова, как вы сказали, и она вызывалась несколько раз с одним и тем же значением указателя, так что, вероятно, это так.

Ben Hommrich 10.12.2020 23:41

изображение = изображение("./текстуры/огонь.jpg"); Это назначение копирования из временного (xvalue). Таким образом, он сначала создает объект и передает указатель pixelData экземпляру изображения. Но сразу после этой строки pixelData освобождается, потому что временный объект уничтожается. Итак, в конце концов, внутри экземпляра изображения уже есть освобожденный указатель.

panky 10.12.2020 23:51
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
4
739
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Конструктор копирования по умолчанию приведет к двойному освобождению. Есть два способа исправить это -

  1. Вы можете обернуть ресурс с помощью unique_ptr с настраиваемым средством удаления, и это в любом случае сделает класс доступным только для перемещения.
  2. Или сделайте его явно не копируемым.

Другие вопросы по теме