Qt 程序在 Windows 中绘制折线时崩溃
Posted
技术标签:
【中文标题】Qt 程序在 Windows 中绘制折线时崩溃【英文标题】:Qt program crashes on polyline drawing in Windows 【发布时间】:2012-06-10 08:08:59 【问题描述】:我开发了一个跨平台的 Qt 程序,它在 QGraphicsScene 上绘制折线:
QPolygonF polygon;
//Init polygon here
for(int i = 0; i < (polygon.size()-1); i++)
float x1 = polygon[i].x();
float y1 = polygon[i].y();
float x2 = polygon[i+1].x();
float y2 = polygon[i+1].y();
QGraphicsLineItem* item = new QGraphicsLineItem(x2, y2, x1, y1);
item->setPen(QPen(QBrush(color), 2));
item->setZValue(30);
item->setData(0, QVariant((int)value));
addItem(item);
程序在收到以下值时在 Windows 上崩溃:
float x1 = 249.573;
float y1 = 183.471;
float x2 = 303.983;
float y2 = 183.45;
这条折线由一条几乎水平的线组成。当直线水平或 y1 和 y2 之间的绝对差为 0 或大于 0.5 时,不会发生崩溃。 它不会在 Ubuntu 上崩溃。
当我将折线更改为多边形时,程序不会崩溃。我最好但丑陋的解决方案是将折线绘制为多边形 - 将相同的点两次附加到多边形:
QPolygonF polygon;
//Init polygon here
for(int i = polygon.size()-1; i > 0; i--)
QPointF point(polygon[i].x(), polygon[i].y());
polygon.append(point);
QGraphicsPolygonItem* item = new QGraphicsPolygonItem(polygon);
item->setPen(QPen(QBrush(color), 2));
item->setZValue(30);
item->setData(0, QVariant((int)value));
addItem(item);
我试图在一个小型且独立的程序中重新创建该错误,该程序在 QGraphicScene 上绘制一条具有相同坐标的线。没有观察到崩溃。
为什么会发生这种崩溃?这个bug有更漂亮的解决方案吗?
顺便说一句,VS2008 调试器中的调用堆栈告诉我崩溃是在由 QtGui4.dll 调用的 msvcr90.dll 中的 malloc.c 中。
技术:
Qt 版本:4.7.0
操作系统:Windows 7 和 Ubuntu
【问题讨论】:
为什么是 addItem(item);在你的代码循环之外? 正如 Frédéric 指出的那样,addItem 放错了位置。循环内的item
变量超出范围,addItem 调用中使用的item
变量与循环内创建的QGraphicsLineItem 无关。
malloc 中的崩溃通常意味着您有堆损坏。损坏本身可能来自代码中的任何地方。
@FrédéricTERRAZZONI 你是对的 - addItem 确实在循环内。我在编辑中修复了这个问题。
@MichaelSlade 您知道在这种情况下,堆损坏是如何发生在 Windows 中而不是 linux 中的吗?
【参考方案1】:
你知道还有QGraphicsPathItem
吗? (QGraphicsPolygonItem
仅适用于闭合多边形,不适用于折线。路径项适用于一般路径。)
您需要从您的QPolygon
构造一个QPainterPath
:
QPainterPath path;
if(polygon.size() > 0) // check this, because we use [0] outside the loop!
path.moveTo(polygon[0]);
for(int i = 1; i < polygon.size(); ++i) // starting from 1 (0 was a "moveTo")
path.lineTo(polygon[i]);
然后制作并使用路径项:
QGraphicsPathItem* item = new QGraphicsPathItem(path);
// your additional code from above:
item->setPen(QPen(QBrush(color), 2));
item->setZValue(30);
item->setData(0, QVariant((int)value));
addItem(item);
但请注意,由于您发布的代码似乎没有错误,因此您的程序中必须存在 严重错误(可能在代码中的不同(可能相关)位置),这无论如何你都应该修好!
坐标的生成可能有错误?或者甚至在生成 QPolygonF 之前进行一些计算?您是否尝试注释掉生成该项目的代码?
您也可以尝试使用适用于 Windows 的 valgrind 替代方案。一些工具见this *** question。
【讨论】:
我不熟悉 QGraphicsPathItem - 现在试试,谢谢!我确实运行了 valgrind,但在 linux 上 - 没有得到足够有趣的东西。我会检查 valgrind 的替代品,希望他们能找到错误... 将代码更改为使用 QPainterPath - 程序仍在崩溃。也许 QGraphicsPathItem 和 QGraphicsLineItem 基本上都以类似的方式画一条直线? @WhiteZebra 我想是的。至少,您现在知道这个类并在这一点上改进了您的代码。 :) 所以你的代码中的另一个位置有一个错误......我更喜欢努力思考并做很多 qDebugs 而不是使用像 valgrind 这样的工具,只要可以找到任何内存泄漏/双重释放/以任何方式.所以我的建议是:仔细阅读你的源代码,每当你阅读一些“危险”的代码时三思而后行,并做大量的调试输出。如果这没有帮助,也许 valgrind 替代品是你的朋友。祝你好运找到错误! ;)以上是关于Qt 程序在 Windows 中绘制折线时崩溃的主要内容,如果未能解决你的问题,请参考以下文章