[solved]Program crashing when calling QSGGeometryNode::setMaterial()
-
EDIT: The program was crashing because I used the compiler option "-fshort-enums", which doesn't play nice with some component in the QSG part of Qt. When I removed the option, things started working again.
I'm trying to modify the QSGGeomteryNode bezier curve example to support a custom color for the curve.
http://qt-project.org/doc/qt-5/qtquick-scenegraph-customgeometry-example.html
@QSGNode *BezierCurve::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
{
QSGGeometryNode *node = 0;
QSGGeometry *geometry = 0;if (!oldNode) { node = new QSGGeometryNode; geometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), m_segmentCount); geometry->setLineWidth(2); geometry->setDrawingMode(GL_LINE_STRIP); node->setGeometry(geometry); node->setFlag(QSGNode::OwnsGeometry); auto material = new QSGFlatColorMaterial; material->setColor(m_strokeColor); node->setMaterial(material); node->setFlag(QSGNode::OwnsMaterial); } else { node = static_cast<QSGGeometryNode *>(oldNode); geometry = node->geometry(); geometry->allocate(m_segmentCount); QSGFlatColorMaterial *material = new QSGFlatColorMaterial; material->setColor(m_strokeColor); node->setMaterial(material); //crash here node->markDirty(QSGNode::DirtyMaterial); } QRectF bounds = boundingRect(); QSGGeometry::Point2D *vertices = geometry->vertexDataAsPoint2D(); for (int i = 0; i < m_segmentCount; ++i) { qreal t = i / qreal(m_segmentCount - 1); qreal invt = 1 - t; QPointF pos = invt * invt * invt * m_p1 + 3 * invt * invt * t * m_p2 + 3 * invt * t * t * m_p3 + t * t * t * m_p4; float x = bounds.x() + pos.x();// * bounds.width(); float y = bounds.y() + pos.y();// * bounds.height(); vertices[i].set(x, y); } node->markDirty(QSGNode::DirtyGeometry); return node;
}@
I've added the lines 21-24, which cause the application to crash.
The debugger shows this:
@HEAP[nmgui.exe]:
Heap block at 26058DC8 modified at 26058DE8 past requested size of 18
HEAP[nmgui.exe]:
Invalid address specified to RtlFreeHeap( 18740000, 26058DD0 )@First stacktrace:
@0 ntdll!TpWaitForAlpcCompletion C:\Windows\system32\ntdll.dll 0x77af0575
1 ?? 0x28d2e0
2 ntdll!RtlLargeIntegerDivide C:\Windows\system32\ntdll.dll 0x77ad57c2
3 ?? 0x2607dcc8
4 ntdll!RtlCopyExtendedContext C:\Windows\system32\ntdll.dll 0x77ab2a8a
5 ?? @If I hit continue in the debugger, I get this stacktrace:
@0 ntdll!TpWaitForAlpcCompletion C:\Windows\system32\ntdll.dll 0x77af0575
1 ?? 0x28d300
2 ntdll!RtlCopyExtendedContext C:\Windows\system32\ntdll.dll 0x77ab2aba
3 ?? 0x26058dc8
4 ntdll!TpQueryPoolStackInformation C:\Windows\system32\ntdll.dll 0x77af15cf
5 ?? 0x26058dc8
6 ntdll!AlpcMaxAllowedMessageLength C:\Windows\system32\ntdll.dll 0x77aaac29
7 ?? 0x18740000
8 ntdll!LdrLoadAlternateResourceModuleEx C:\Windows\system32\ntdll.dll 0x77a534a2
9 ?? 0x26058dc8
10 msvcrt!free C:\Windows\syswow64\msvcrt.dll 0x774898cd
11 ?? 0x18740000
12 QSGFlatColorMaterial::~QSGFlatColorMaterial qsgflatcolormaterial.h 50 0x126a54fe
13 QSGGeometryNode::setMaterial qsgnode.cpp 946 0x12509a8f
14 BezierCurve::updatePaintNode beziercurve.cpp 152 0x40928d
15 QQuickWindowPrivate::updateDirtyNode qquickwindow.cpp 2535 0x12552234
16 QQuickWindowPrivate::updateDirtyNodes qquickwindow.cpp 2360 0x125514a4
17 QQuickWindowPrivate::syncSceneGraph qquickwindow.cpp 334 0x1254a690
18 QSGWindowsRenderLoop::renderWindow qsgwindowsrenderloop.cpp 452 0x1253192d
19 QSGWindowsRenderLoop::render qsgwindowsrenderloop.cpp 395 0x12531670
20 QSGWindowsRenderLoop::event qsgwindowsrenderloop.cpp 375 0x12531610
... <More> @Am I doing something wrong? How can I change material of the line without crashing the application?
-
Hi,
@node = static_cast<QSGGeometryNode *>(oldNode);@
That's dangerous, are you sur oldNode contains somethign valid ?
You should rather use dynamic_cast plus a null check.Hope it helps
-
Yes, this was what I though as well, but it's what's done in the example.
There is a null check for oldNode, because it will only enter that branch if !oldNode (line 6), which means it's not null.
I Tried doing a dynamic cast instead, but it didn't make a difference.
EDIT: The problem seems to be something else. It's still crashing with the original example code, although after I close the window.
-
After hours of commenting out and replacing code in my own project to find what was causing the bug, I think I've finally found it.
I was using C++11, and apparently some part of Qt doesn't really like that (might also be a compiler bug, but this probably unlikely).
Having
@QMAKE_CXXFLAGS += -std=c++11@
In the .pro file is the only difference between a working and a crashing program.EDIT:
Nope, made a fool of myself again (probably forgot to run qmake or clean when i verified the offending line). std-c++11 was not the problem.It is the compiler option -fshort-enums, which tells the compiler to allocate as many bytes as needed for enumerated types. Apparently Qt is not happy with that.
-
I can't comment about the short-enums problem, but the interest mailing list would be a good starting point for that one.
On a side note, if you want to use C++11, you can simply add
@CONFIG += c++11@
to your pro file