PDA

View Full Version : QT 5.6: Segmentation violation in second call to QGraphicsScene::addItem()



wlstrong
16th May 2016, 20:26
I keep getting a segmentation violation in my second call to QGraphicsScene::addItem().

The following code works the first time, but after terminating/reloading QDialog, QApplication, etc. (called in a DLL), code fails consistently on second use!?! Makes me wonder if the destructors terminated cleanly, or if I might have reinitialize QApplication differently.

Suggestions, please? Here is my code in question...



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

PBITMAPINFOHEADER pDIBInfoHeader; //populated elsewhere
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;
ppm->convertFromImage(qiFlip.scaled(qs, Qt::KeepAspectRatio), Qt::NoFormatConversion);
SIGSEGV >>> pgs->addItem(ppm);

ui->grXray->setScene(pgs); // set the scene into QGraphicsView


Notes: pgs is the only item in the scene. The scene is not active


I rebuilt QT with debug options for Windows MSVC 2015, and can see lots of detail, but the intricacies of C++ templates, QVariant and QMetaType escape me.

Where should I look for corruption?

Thanks, Lee



Here is more detail of SIGSEGV:

CALL STACK
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 snippets:

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;
}
}


Is p.d.type=1028 valid for Qvariant type?






Value of p:
- d {data={c=32 ' ' uc=32 ' ' s=-13536 ...} type=1028 is_shared=0 ...} QVariant::Private
- data {c=32 ' ' uc=32 ' ' s=-13536 ...} QVariant::Private::Data
c 32 ' ' char
uc 32 ' ' unsigned char
s -13536 short
sc 32 ' ' char
us 52000 unsigned short
i 108055328 int
u 108055328 unsigned int
l 108055328 long
ul 108055328 unsigned long
b true (32) bool
d 3.6078682250845646e-308 double
f 4.52882158e-35 float
real 3.6078682250845646e-308 double
ll 7302406583929632 __int64
ull 7302406583929632 unsigned __int64
+ o 0x0670cb20 {...} QObject * {QuickRayHD.ds!QGraphicsScene}
ptr 0x0670cb20 void *
+ shared 0x0670cb20 {ptr=0x0394846c {QuickRayHD.ds!const QGraphicsScene::`local vftable'} ref={...} } QVariant::PrivateShared *
type 1028 unsigned int
is_shared 0 unsigned int
is_null 0 unsigned int


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)));



Value of this 0x0670cb20 {...} QGraphicsScene * {QuickRayHD.ds!QGraphicsScene}
- [QGraphicsScene] {...} QuickRayHD.ds!QGraphicsScene
- QObject {d_ptr=scoped pointer to a dynamically allocated object of type "QObjectData" } QuickRayHD.ds!QObject
+ __vfptr 0x0394846c {QuickRayHD.ds!const QGraphicsScene::`local vftable'} {0x03930436 {QuickRayHD.ds!QGraphicsScene::metaObject(void)con st }, ...} void * *
- d_ptr scoped pointer to a dynamically allocated object of type "QObjectData" QuickRayHD.ds!QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> >
[is null] false bool
- [Raw View] {d=0x066f5cc0 {changedSignalIndex=3 processDirtyItemsIndex=20 polishItemsIndex=19 ...} } QuickRayHD.ds!QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> >
- d 0x066f5cc0 {changedSignalIndex=3 processDirtyItemsIndex=20 polishItemsIndex=19 ...} QuickRayHD.ds!QObjectData * {QGraphicsScenePrivate}
- [QGraphicsScenePrivate] {changedSignalIndex=3 processDirtyItemsIndex=20 polishItemsIndex=19 ...} QGraphicsScenePrivate
+ QObjectPrivate {extraData=0x00000000 <NULL> threadData=0x005cc3e8 {_ref={...} loopLevel=1 eventLoops={ size = 0 } ...} ...} QObjectPrivate
changedSignalIndex 3 int
processDirtyItemsIndex 20 int
polishItemsIndex 19 int
indexMethod BspTreeIndex (0) QGraphicsScene::ItemIndexMethod
+ index 0x0670ca40 {...} QGraphicsSceneIndex * {QGraphicsSceneBspTreeIndex}
lastItemCount 0 int
+ sceneRect { x = 0.00000000000000000, y = 0.00000000000000000, width = 70.000000000000000, height = 80.000000000000000 } QRectF
hasSceneRect 1 unsigned int
dirtyGrowingItemsBoundingRect 1 unsigned int
updateAll 1 unsigned int
calledEmitUpdated 1 unsigned int
processDirtyItemsEmitted 0 unsigned int
needSortTopLevelItems 1 unsigned int
holesInTopLevelSiblingIndex 0 unsigned int
topLevelSequentialOrdering 1 unsigned int
scenePosDescendantsUpdatePending 0 unsigned int
stickyFocus 0 unsigned int
hasFocus 0 unsigned int
lastMouseGrabberItemHasImplicitMouseGrab 0 unsigned int
allItemsIgnoreHoverEvents 1 unsigned int
allItemsUseDefaultCursor 1 unsigned int
painterStateProtection 1 unsigned int
sortCacheEnabled 0 unsigned int
allItemsIgnoreTouchEvents 1 unsigned int
padding 26342 unsigned int
minimumRenderSize 0.00000000000000000 double
+ growingItemsBoundingRect { x = 0.00000000000000000, y = 0.00000000000000000, width = 0.00000000000000000, height = 0.00000000000000000 } QRectF
+ updatedRects { size = 0 } QList<QRectF>
+ selectionArea {d_ptr=scoped pointer to a dynamically allocated object of type "QPainterPathPrivate" } QPainterPath
selectionChanging 0 int
+ selectedItems { size = 0 } QSet<QGraphicsItem *>
+ unpolishedItems { size = 0 } QVector<QGraphicsItem *>
+ topLevelItems { size = 0 } QList<QGraphicsItem *>
+ movingItemsInitialPositions { size = 0 } QHash<QGraphicsItem *,QPointF>
+ scenePosItems { size = 0 } QSet<QGraphicsItem *>
+ backgroundBrush {d=scoped pointer to a dynamically allocated object of type "QBrushData" } QBrush
+ foregroundBrush {d=scoped pointer to a dynamically allocated object of type "QBrushData" } QBrush
rectAdjust 2 unsigned int
+ focusItem 0x00000000 <NULL> QGraphicsItem *
+ lastFocusItem 0x00000000 <NULL> QGraphicsItem *
+ passiveFocusItem 0x00000000 <NULL> QGraphicsItem *
+ tabFocusFirst 0x00000000 <NULL> QGraphicsWidget *
+ activePanel 0x00000000 <NULL> QGraphicsItem *
+ lastActivePanel 0x00000000 <NULL> QGraphicsItem *
activationRefCount 0 int
childExplicitActivation 0 int
+ popupWidgets { size = 0 } QList<QGraphicsWidget *>
+ lastMouseGrabberItem 0x00000000 <NULL> QGraphicsItem *
+ mouseGrabberItems { size = 0 } QList<QGraphicsItem *>
+ keyboardGrabberItems { size = 0 } QList<QGraphicsItem *>
+ dragDropItem 0x00000000 <NULL> QGraphicsItem *
+ enterWidget 0x00000000 <NULL> QGraphicsWidget *
lastDropAction IgnoreAction (0) Qt::DropAction
+ cachedItemsUnderMouse { size = 0 } QList<QGraphicsItem *>
+ hoverItems { size = 0 } QList<QGraphicsItem *>
+ lastSceneMousePos { x = 0.00000000000000000, y = 0.00000000000000000 } QPointF
+ mouseGrabberButtonDownPos { size = 0 } QMap<enum Qt::MouseButton,QPointF>
+ mouseGrabberButtonDownScenePos { size = 0 } QMap<enum Qt::MouseButton,QPointF>
+ mouseGrabberButtonDownScreenPos { size = 0 } QMap<enum Qt::MouseButton,QPoint>
+ views { size = 0 } QList<QGraphicsView *>
+ sceneEventFilters { size = 0 } QMultiMap<QGraphicsItem *,QGraphicsItem *>
+ style 0x00000000 <NULL> QStyle *
+ font {d=pointer to explicit shared object of type "QFontPrivate" resolve_mask=0 } QFont
+ palette {d=0x0064f5e8 {...} data={current_group=0 resolve_mask=0 } for_faster_swapping_dont_use=0 } QPalette
+ styleOptionTmp {exposedRect={ x = 0.00000000000000000, y = 0.00000000000000000, width = 0.00000000000000000, height = 0.00000000000000000 } ...} QStyleOptionGraphicsItem
+ sceneCurrentTouchPoints { size = 0 } QMap<int,QTouchEvent::TouchPoint>
+ itemForTouchPointId { size = 0 } QMap<int,QGraphicsItem *>
+ cachedTargetItems { size = 0 } QList<QGraphicsObject *>
+ cachedItemGestures { size = 0 } QHash<QGraphicsObject *,QSet<QGesture *> >
+ cachedAlreadyDeliveredGestures { size = 0 } QHash<QGraphicsObject *,QSet<QGesture *> >
+ gestureTargets { size = 0 } QHash<QGesture *,QGraphicsObject *>
+ grabbedGestures { size = 0 } QHash<enum Qt::GestureType,int>
+ modalPanels { size = 0 } QList<QGraphicsItem *>
+ __vfptr 0x64b11d18 {Qt5Widgetsd.dll!const QGraphicsScenePrivate::`vftable'} {0x644dcf99 {Qt5Widgetsd.dll!QGraphicsScenePrivate::`vector deleting destructor'(unsigned int)}} void * *
+ q_ptr 0x0670cb20 {...} QuickRayHD.ds!QObject * {QuickRayHD.ds!QGraphicsScene}
+ parent 0x00000000 <NULL> QuickRayHD.ds!QObject *
+ children {p={d=0x066c4ce8 {ref={atomic={_q_value=1 } } alloc=4 begin=0 ...} } d=0x066c4ce8 {ref={atomic={_q_value=...} } ...} } QuickRayHD.ds!QList<QObject *>
isWidget 0 unsigned int
blockSig 0 unsigned int
wasDeleted 0 unsigned int
isDeletingChildren 0 unsigned int
sendChildEvents 1 unsigned int
receiveChildEvents 1 unsigned int
isWindow 0 unsigned int
unused 26975131 unsigned int
postedEvents 1 int
metaObject 0x00000000 <NULL> QuickRayHD.ds!QDynamicMetaObjectData *

anda_skoa
16th May 2016, 20:38
Is "ppm" properly initialized?

Cheers,
_

wlstrong
16th May 2016, 21:46
Yes the original snippet omitted key lines :eek:

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;
ppm->convertFromImage(qiFlip.scaled(qs, Qt::KeepAspectRatio), Qt::NoFormatConversion);
QGraphicsPixmapItem *item = new QGraphicsPixmapItem(*ppm, 0);
delete ppm;

pgs->addItem(item);
ui->grXray->setScene(pgs);

d_stranz
16th May 2016, 23:47
ppm->convertFromImage(qiFlip.scaled(qs, Qt::KeepAspectRatio), Qt::NoFormatConversion);

What makes you so confident that this method worked? Or that qiFlip is non-null? You aren't checking any return values, and if there is a bad image in there constructing a QGraphicsPixmapItem from a null pixmap probably isn't going to work all that well.

wlstrong
17th May 2016, 14:15
QPixmap::convertFromImage() worked the first time, and the same image was displayed, but to make sure about the second call, I added a check:

if (QPixmap::convertFromImage(...)) and it was true.

Tx

d_stranz
17th May 2016, 18:47
What happens if you call QGraphicsScene::addPixmap()? And it isn't necessary to allocate all these image instances on the heap if all you are going to do is use them for conversions and then throw them away.



uchar *pBits = (uchar *)m_pImage + sizeof(BITMAPINFOHEADER);
QImage qi((uchar *)pBits, width, height, QImage::Format_Grayscale8);
QImage qiFlip = qi.mirrored(false, true); //flip image vertically

QPixmap pm;
pm.convertFromImage(qiFlip.scaled(qs, Qt::KeepAspectRatio), Qt::NoFormatConversion);

pgs->addPixmap( pm );

wlstrong
17th May 2016, 19:48
Thanks, I tried your suggestions, with similar SIGSEGV on second invocation :

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 2494 C++
QGraphicsScene::addPixmap(const QPixmap & pixmap) Line 2749 C++

d_stranz
18th May 2016, 03:08
with similar SIGSEGV on second invocation

What "second invocation"? You only add the pixmap once to the scene after both the scene and pixmap are created, at least in the code you have shown so far. Have you omitted maybe a few more "key lines" from your snippet?

If you want help in solving the problem, you are going to have to post at least enough of the code in context so we can get an idea of what might be going wrong. It isn't in the code you have posted thus far.

And please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.