Я использую некоторую вилку QMapControl и обнаружил ошибку. GeometryPointImage имеет геттер для изображения const QPixmap& image() const
:
const QPixmap& GeometryPointImage::image() const
{
// Is the image pixmap currently null?
if (m_image == nullptr) { //std::shared_ptr<QPixmap> m_image;
// Have we already constructed the null image pixmap?
if (m_image_null == nullptr) { //std::unique_ptr<QPixmap> m_image_null;
// Construct the null image pixmap.
m_image_null.reset(new QPixmap);
}
// Return the null image pixmap.
return *(m_image_null.get());
} else {
// Return the image pixmap.
return *(m_image.get());
}
}
Существуют различные сеттеры для m_image
, а image()
геттер используется в функции draw()
:
painter.drawPixmap(-pixmap_rect_px.rawRect().width() / 2.0, -pixmap_rect_px.rawRect().height() / 2.0, image()); // void drawPixmap(int x, int y, const QPixmap &pm)
Я могу уловить такое поведение: draw()
вызовы функций image()
, которые разыменовывают общий указатель, он переходит в drawPixmap
и некоторые другие вызовы событий setImage()
, где m_image
присваивает новое значение и деструктор из общего указателя разрушает объект QPixmap
, на который ссылается drawPixmap()
, а затем приложение переходит в SIGSEGV.
Я думаю, что геттер, который возвращает ссылку на что-то, принадлежащее общему указателю, не является такой хорошей практикой, но какое решение является наиболее подходящим? Я не хочу копировать объект QPixMap
или добавлять мьютекс в геттеры, сеттеры и draw()
. Есть ли способ продлить жизнь указанного объекта (возможно, с чем-то похожим на qAsConst
)? Должен ли геттер возвращать std::shared_ptr<QPixmap>
?
UPD: Подробно: setImage()
вызывается из основного потока, и ожидается, что этот сеттер излучает сигнал для перерисовки объекта. Но основной класс QMapControl также использует QtConcurrent::run()
для перерисовки всей сцены и касается растрового изображения из какого-то другого потока. И поток №1 удаляет объект, когда поток, например, №6 (или №7) выполняет drawPixmap()
.