2016-05-17 21 views
0

Ich erhalte eine Segmentierungsverletzung in meinem zweiten Aufruf an QGraphicsScene :: addItem().QT 5.6: Segmentierungsverletzung im zweiten Aufruf von QGraphicsScene :: addItem()

Der folgende Code funktioniert das erste Mal, aber nach dem Beenden/Neuladen von QDialog, QApplication, etc. (aufgerufen in einer DLL), Fehler Code konsequent bei der zweiten Verwendung mit dem gleichen Bild!?!

Ich frage mich, ob die Destruktoren sauber beendet wurden, oder ob ich QApplication möglicherweise neu initialisieren muss.

Vorschläge, bitte? Hier ist mein Code in Frage ...

PBITMAPINFOHEADER pDIBInfoHeader = (PBITMAPINFOHEADER)m_pImage; 
    QGraphicsScene *pgs = new QGraphicsScene(); 
    pgs->setSceneRect(0.0, 0.0, 70.0, 80.0); 
    QSize qs(70, 80); 

    int width = pDIBInfoHeader->biWidth; 
    int height = pDIBInfoHeader->biHeight; 

    uchar *pBits = (uchar *)m_pImage + sizeof(BITMAPINFOHEADER); 
    QImage *pqi = new QImage((uchar *)pBits, width, height, QImage::Format_Grayscale8); 
    QImage qiFlip = pqi->mirrored(false, true);   //flip image vertically 
    delete pqi; 

    QPixmap *ppm = new QPixmap; 
    if (!ppm->convertFromImage(qiFlip.scaled(qs, Qt::KeepAspectRatio), Qt::NoFormatConversion)) 
     cdbg << "ppm->convertFromImage false" << endl; 

    // DOES QGRAPHICSPIXMAPITEM TAKE OWNERSHIP OF QPIXMAP? 
    QGraphicsPixmapItem *item = new QGraphicsPixmapItem(*ppm, 0);  

    delete ppm; 

    pgs->addItem(item); // <<< SIGSEGV 
    ui->grXray->setScene(pgs); 

Hinweise: Pgs ist das einzige Element in der Szene. Die Szene ist nicht aktiv.

Ich habe QT mit Debug-Optionen für Windows MSVC 2015 neu aufgebaut und kann viele Details sehen, aber die Feinheiten von C++ - Vorlagen, QVariant und QMetaType entgehen mir. Wo soll ich nach Korruption suchen?

Hier ist Call-Stack von SIGSEGV:

QMetaType::construct(void * where, const void * copy) Line 2153 C++ 
`anonymous namespace'::customConstruct(QVariant::Private * d, const void * copy) Line 1020 C++ 
QVariant::QVariant(const QVariant & p) Line 1372 C++ 
QGraphicsItem::itemChange(QGraphicsItem::GraphicsI temChange change, const QVariant & value) Line 7447 C++ 
QGraphicsScene::addItem(QGraphicsItem * item) Line 2496 C++ 

QT Code-Schnipsel:

inline void *QMetaType::construct(void *where, const void *copy) const 
{ 
if (Q_UNLIKELY(isExtended(ConstructEx))) 
return constructExtended(where, copy); 
return m_constructor(where, copy);     //<<<<<<<< 
} 


QVariant::QVariant(const QVariant &p) 
: d(p.d) 
{ 
if (d.is_shared) { 
d.data.shared->ref.ref(); 
} else if (p.d.type > Char) { 
handlerManager[d.type]->construct(&d, p.constData()); //<<<<<< 
d.is_null = p.d.is_null; 
} 
} 


void QGraphicsScene::addItem(QGraphicsItem *item) 
... 
// Notify the item that its scene is changing, and allow the item to 
// react. 
const QVariant newSceneVariant(item->itemChange(QGraphicsItem::ItemSceneChange, 
QVariant::fromValue<QGraphicsScene *>(this))); // <<<<<<<<< 
+0

Müssen Sie Ihr QApplication-Objekt wirklich zerstören und neu erstellen? Die meisten Qt-Programme behalten ein einzelnes QApplication-Objekt für die Dauer des Prozesses bei (z. B. als ein Stapelobjekt nahe dem Anfang von main() oder Ähnlichem deklariert); Ich vermute, dass das Zerstören und Wiederherstellen des QApplication-Objekts etwas ist, das die Qt-Entwickler nicht erwartet haben, so dass dort ein Fehler liegen kann, den sie nicht kennen. –

+0

Hmm, unser Anwendungsframework löscht QApplication bei Beendigung. Ich habe versucht, dieses Löschen zu überspringen, und habe SIGSEGV immer noch tief in QCoreApplication :: postEvent(); – Lee

Antwort

0

Es gibt keine Notwendigkeit für pqi noch ppm auf dem Heap gebaut werden. Auch Sie zerstören ppm, während es noch benutzt wird.

wäre eine sauberere Version des Codes sein:

QImage image((uchar *)pBits, width, height, QImage::Format_Grayscale8); 
QImage flippedImage = image.mirrored(false, true); //flip image vertically 
QPixmap pixmap = QPixmap::fromImage(flippedImage.scaled(qs, Qt::KeepAspectRatio));  
pgs->addPixmap(pixmap); 

Der Code selbst kürzer gemacht werden kann, aber es wird weniger lesbar zu sein beginnen.

+0

AFAICT die "Sie zerstören ppm, während es noch in Betrieb ist" ist nicht wahr. Fehle ich etwas? –

+0

Nein, du hast das nicht, dieser Satz sollte gelöscht werden, nachdem ich bemerkt habe, dass ich das Codebeispiel falsch gelesen habe. Da QPixmap eine implizit gemeinsam genutzte Klasse ist, ist das Löschen in dieser Reihenfolge OK, da der Referenzzähler nur dekrementiert werden soll. – SGaist

Verwandte Themen