Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Segmentation fault when using QImage/QPainter functions (e.g. QImage::scaledToWidth, QPainter::drawImage) in certain situations

Segmentation fault when using QImage/QPainter functions (e.g. QImage::scaledToWidth, QPainter::drawImage) in certain situations

Scheduled Pinned Locked Moved General and Desktop
2 Posts 1 Posters 3.7k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • T Offline
    T Offline
    tomq
    wrote on last edited by
    #1

    I'm working on the migration of a large Qt 4.8/mingw 4.4 application from Windows 7 to Windows 8. When watermarking images, I get a segmentation fault. It is possible to work around the bug (I've been able to get a half-decent looking result using clipping in place of the alpha channel). However I'm interested in figuring out if this is a bug in the Qt libraries - especially since we could get similar issues in the future if we do not have a good understanding of the bug.

    Configuration:

    • Qt 4.8.4, mingw 4.4. Qt 4.8.5 also crashed.
    • Windows 8.0 or 8.1
    • The crash occurs on debug builds only, independently of whether or not a debugger is attached

    Crash scenario:

    • Have a GUI thread running
    • Create a QImage from a png file that has an alpha channel (=transparency)
    • Attempt to resize the image with QImage::scaledToWidth(width), but not in the GUI thread

    No crash if either is true:

    • OS is windows 7
    • There is no alpha channel
    • The scaledToWidth call is made from the GUI thread
    • There is no concurrent GUI thread

    Stacktrace:
    0 _mm_andnot_si128 emmintrin.h 1239 0x8a6572
    1 comp_func_SourceOver_sse2 qdrawhelper_sse2.cpp 152 0x8a6572
    2 BlendSrcGeneric<(SpanMethod)0>::process qdrawhelper.cpp 3581 0xf4cf7b
    3 handleSpans<BlendSrcGeneric<(SpanMethod)0> > qdrawhelper.cpp 3527 0xf020eb
    4 blend_src_generic<(SpanMethod)0> qdrawhelper.cpp 3599 0xa764a1
    5 qBlendTexture qdrawhelper.cpp 6832 0xa67159
    6 fillRect_normalized qpaintengine_raster.cpp 1494 0xa55b4b
    7 QRasterPaintEngine::drawImage qpaintengine_raster.cpp 2407 0xa5a4db
    8 QRasterPaintEngine::drawImage qpaintengine_raster.cpp 2169 0xa58ef8
    9 QPainter::drawImage qpainter.cpp 5636 0x9eae0a
    10 QPainter::drawImage qpainter.h 928 0x1047ca1
    11 QImage::transformed qimage.cpp 6672 0x95861e
    12 QImage::scaledToWidth qimage.cpp 4498 0x951c4b
    13 WatermarkTest::watermark watermarktest.cpp 83 0x4023dd
    14 QtConcurrent::StoredFunctorCall0<void, void (*)()>::runFunctor qtconcurrentstoredfunctioncall.h 74 0x407a96
    15 QtConcurrent::RunFunctionTask<void>::run qtconcurrentrunbase.h 134 0x4078e3
    16 QThreadPoolThread::run qthreadpool.cpp 107 0x69ccd310
    17 QThreadPrivate::start qthread_win.cpp 346 0x69cd7eb5
    18 wtoi64 C:\WINDOWS\SysWOW64\msvcrt.dll 0x76fb0bc4
    19 msvcrt!_beginthreadex C:\WINDOWS\SysWOW64\msvcrt.dll 0x76fb0cec
    20 KERNEL32!GetNumberOfConsoleFonts C:\WINDOWS\SysWOW64\kernel32.dll 0x74fc495d
    21 ?? 0x773d98ee
    22 ?? 0x773d98c4
    23 ??

    Notes about the stacktrace:
    emmintrin.h seems to be a MinGW file (not completely sure). The function that is macro-ed consists of a single line thanks to multiple "", but it seems (?) that the crash occurs on line 176 of emmintrin.h (based on the status of initialized variables at the time of the segmentation fault). I think this is very low level code for processing pixel value changes.

    I'm including code for a small application that reproduces the crash in a second post (due to the character limit).

    1 Reply Last reply
    0
    • T Offline
      T Offline
      tomq
      wrote on last edited by
      #2

      Code:
      In the process of figuring out the cause, I made a small application (still roughly 150 lines...) to reproduce the crash and show scenarios in which it does versus does not occur:

      File: watermarktest.h
      @
      #ifndef WATERMARKTEST_H
      #define WATERMARKTEST_H

      #include <QMainWindow>
      #include <QLabel>
      #include <QVBoxLayout>
      #include <QPushButton>

      class WatermarkTest : public QMainWindow
      {
      Q_OBJECT
      public:
      explicit WatermarkTest(QWidget *parent = 0);

      signals:

      public slots:
      void addRemoveWatermark();
      void addWatermarkAsync();
      void addWatermarkSync();

      private: //functions
      static void watermark();

      private: //variables
      QPixmap m_pix;
      QLabel *m_imageViewer;
      QPushButton *m_buttonApplyWatermark;
      QPushButton *m_buttonAsyncWatermark;
      QPushButton *m_buttonSyncWatermark;
      QVBoxLayout *m_layout;
      QWidget *m_central;
      bool m_watermarkOn;

      static const QString BACKGROUND;
      static const QString WATERMARK;
      

      };

      #endif // WATERMARKTEST_H
      @

      File: watermarktest.cpp
      @
      #include "watermarktest.h"
      #include <QPainter>
      #include <QtConcurrentRun>

      const QString WatermarkTest::BACKGROUND = "C:/Development/baseImage.png";
      const QString WatermarkTest::WATERMARK = "C:/Development/alpha.png"; //This image has an alpha channel

      WatermarkTest::WatermarkTest(QWidget *parent) :
      QMainWindow(parent),
      m_watermarkOn(false)
      {
      setWindowTitle("Windows 8 watermark crash replication");

      m_imageViewer = new QLabel();
      m_buttonApplyWatermark = new QPushButton("add/remove watermark");
      m_buttonSyncWatermark = new QPushButton("main thread watermark");
      m_buttonAsyncWatermark = new QPushButton("asynchronous watermark");
      m_layout = new QVBoxLayout();--
      m_pix = QPixmap(BACKGROUND);
      m_central = new QWidget();
      
      m_imageViewer->setPixmap(m_pix);
      
      connect(m_buttonApplyWatermark, SIGNAL(clicked()), this, SLOT(addRemoveWatermark()));
      connect(m_buttonAsyncWatermark, SIGNAL(clicked()), this, SLOT(addWatermarkAsync()));
      connect(m_buttonSyncWatermark, SIGNAL(clicked()), this, SLOT(addWatermarkSync()));
      
      
      m_layout->addWidget(m_imageViewer);
      m_layout->addWidget(m_buttonApplyWatermark);
      m_layout->addWidget(m_buttonAsyncWatermark);
      m_layout->addWidget(m_buttonSyncWatermark);
      
      m_central->setLayout(m_layout);
      setCentralWidget(m_central);
      

      }

      void WatermarkTest::addRemoveWatermark() //works
      {
      if(!m_watermarkOn)
      {
      QImage bg(BACKGROUND);
      QPainter painter(&bg);
      painter.setRenderHint(QPainter::Antialiasing, true);
      int width = 160;
      QImage watermark(WATERMARK);

          QImage scaledImg = watermark.scaledToWidth(width);
          painter.drawImage(0, 0, scaledImg);
      
          painter.end();
          m_imageViewer->setPixmap(QPixmap::fromImage(bg));
          m_watermarkOn = true;
      }
      else
      {
          QImage bg(BACKGROUND);
          m_imageViewer->setPixmap(QPixmap::fromImage(bg));
          m_watermarkOn = false;
      }
      

      }

      void WatermarkTest::addWatermarkSync()
      {
      watermark(); //works
      }

      void WatermarkTest::addWatermarkAsync()
      {
      QtConcurrent::run(watermark); //seg fault
      }

      void WatermarkTest::watermark()
      {
      QImage bg(BACKGROUND);
      QPainter painter(&bg);
      painter.setRenderHint(QPainter::Antialiasing, true);
      QImage watermark(WATERMARK);

      //scenario 1
      int width = 160;
      QImage scaledImg = watermark.scaledToWidth(width); //causes crash, iff called via addWatermarkAsync
      painter.drawImage(0, 0, scaledImg);
      
      //scenario 2
      //painter.drawImage(0, 0, watermark); //causes crash if scenario 1 is commented out
      
      painter.end();
      bg.save("C:/Development/savedfile.png");
      

      }
      @

      File: main.cpp
      @
      #include <watermarktest.h>
      #include <QApplication>

      int main(int argc, char *argv[])
      {
      QApplication app(argc, argv);

      WatermarkTest test;------
      test.show();
      
      return app.exec();
      

      }
      @

      Sample image file with alpha channel so you don't have to make your own
      !http://i42.tinypic.com/30xkke1.png(Alpha image for watermark)!

      1 Reply Last reply
      0

      • Login

      • Login or register to search.
      • First post
        Last post
      0
      • Categories
      • Recent
      • Tags
      • Popular
      • Users
      • Groups
      • Search
      • Get Qt Extensions
      • Unsolved