這個Qt程式中的一段代碼導致程式崩潰但沒有執行。
程式由main.cpp、mainwindow.cpp、mainwindow.h、mainwindow.ui和CMakeLists.txt組成,問題主要出在MainWindow類。
主視窗.h:
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QPainter>
#include <QMouseEvent>
#include <QColorDialog>
#include <vector>
#include <cmath>
#include <cstdio>
#define Pi 3.1415926535897932
#define MAXHEIGHT 4320
#define MAXWIDTH 7680
using namespace std;
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
enum State{NONE,RECT,CIRCLE,POLYGON,CUBE,BEZIER};
struct Circle
{
int x;
int y;
double r;
};
struct Pos
{
int x;
int y;
};
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
protected:
void paintEvent(QPaintEvent*);
void mousePressEvent(QMouseEvent*);
void mouseReleaseEvent(QMouseEvent*);
void mouseMoveEvent(QMouseEvent*);
void DDALine(QPainter* painter, int x1, int y1, int x2, int y2);
void BresenhamCircle(QPainter* painter, int x, int y, int r);
void Polygon(QPainter* painter, vector<Pos> cpolygon);
State state=NONE;
vector<QRect> rects;
vector<Circle> circles;
vector<vector<Pos>> polygons;
vector<Pos> currentPolygon;
QPoint* movePoint=nullptr;
vector<Pos> curPaintPolygon;
int rectX1=0;
int rectY1=0;
int circleX1=0;
int circleY1=0;
QColor penColor=Qt::black;
QImage img;
};
#endif // MAINWINDOW_H
主視窗.cpp:
#include "mainwindow.h"
#include "./ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent)
, ui(new Ui::MainWindow)
{
ui->setupUi(this);
if(!(img.load("/Users/lijiabo/Documents/GitHub/CGWORK0528/0528.png")))
throw "Image loading failed!";
//connect menu actions
connect(ui->actionDrawRect,&QAction::triggered,this,[=](){
this->state=RECT;
});
connect(ui->actionDrawCircle,&QAction::triggered,this,[=](){
this->state=CIRCLE;
});
connect(ui->actionSetColor,&QAction::triggered,this,[=](){
penColor=QColorDialog::getColor(penColor,this,"設定顏色");
update(rect());
});
connect(ui->actionDrawPolygon,&QAction::triggered,this,[=](){
this->state=POLYGON;
});
connect(ui->actionSetColor_2,&QAction::triggered,this,[=](){
penColor=QColorDialog::getColor(penColor,this,"設定顏色");
update(rect());
});
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::paintEvent(QPaintEvent *)
{
QPainter painter(this);
painter.setPen(penColor);
//DEBUG
painter.drawText(rect(),QString("Width: " QString::number(rect().width()) " Height: " QString::number(rect().height())));
switch(state)
{
case RECT:
case CIRCLE:
for(QRect rect:rects)
{
DDALine(&painter,rect.topLeft().x(),rect.topLeft().y(),rect.topRight().x(),rect.topRight().y());//top
DDALine(&painter,rect.bottomLeft().x(),rect.bottomLeft().y(),rect.bottomRight().x(),rect.bottomRight().y());//bottom
DDALine(&painter,rect.topLeft().x(),rect.topLeft().y(),rect.bottomLeft().x(),rect.bottomLeft().y());//left
DDALine(&painter,rect.topRight().x(),rect.topRight().y(),rect.bottomRight().x(),rect.bottomRight().y());//right
}
for(Circle c:circles)
BresenhamCircle(&painter,c.x,c.y,(int)c.r);
break;
case POLYGON:
if(currentPolygon.size()>=1)
{
//把currentPolygon復制給curPaintPolygon
curPaintPolygon.clear();
for(Pos point:currentPolygon)
{
curPaintPolygon.push_back({point.x,point.y});
}
if(movePoint!=nullptr)
curPaintPolygon.push_back({movePoint->x(),movePoint->y()});
Polygon(&painter,curPaintPolygon);
}
if(polygons.size()>0)
{
for(vector<Pos> polygon:polygons)
{
Polygon(&painter,polygon);
}
}
break;
case CUBE:
break;
case BEZIER:
break;
default:
;
}
}
void MainWindow::mousePressEvent(QMouseEvent *event)
{
switch(state)
{
case RECT:
rectX1=event->pos().x();
rectY1=event->pos().y();
rects.push_back(QRect(rectX1,rectY1,0,0));
break;
case CIRCLE:
circleX1=event->pos().x();
circleY1=event->pos().y();
circles.push_back({circleX1,circleY1,1});
break;
case POLYGON:
/*
if(currentPolygon==nullptr)
{
currentPolygon=new QPolygon;
currentPolygon->append(QPoint(event->pos().x(),event->pos().y()));
}
else
*/
movePoint= nullptr;
currentPolygon.push_back({event->pos().x(),event->pos().y()});
break;
case CUBE:
break;
case BEZIER:
break;
default:
;
}
update(rect());
}
void MainWindow::mouseReleaseEvent(QMouseEvent *event)
{
switch(state)
{
case RECT:
break;
case CIRCLE:
break;
case POLYGON:
if(event->button()==Qt::LeftButton)
{
if(currentPolygon.size()>1)
polygons.push_back(currentPolygon);
currentPolygon.clear();
if(movePoint!=nullptr)
delete movePoint;
movePoint=nullptr;
}
break;
case CUBE:
break;
case BEZIER:
break;
default:
;
}
update(rect());
}
void MainWindow::mouseMoveEvent(QMouseEvent *event)
{
switch(state)
{
case RECT:
rects.back().setCoords(rectX1,rectY1,event->pos().x(),event->pos().y());
break;
case CIRCLE:
circles.back().r=sqrt((event->pos().x()-circleX1)*(event->pos().x()-circleX1) (event->pos().y()-circleY1)*(event->pos().y()-circleY1));
break;
case POLYGON:
if(movePoint==nullptr)
movePoint=new QPoint(event->pos().x(),event->pos().y());
else
*movePoint=event->pos();
break;
case CUBE:
break;
case BEZIER:
break;
default:
;
}
update(rect());
}
void MainWindow::DDALine(QPainter* painter, int x1, int y1, int x2, int y2)
{
double dx, dy, e, x, y;
dx = x2 - x1;
dy = y2 - y1;
e = (fabs(dx) > fabs(dy)) ? fabs(dx) : fabs(dy);
dx /= e;
dy /= e;
x = x1;
y = y1;
for (int i = 1; i <= e; i )
{
painter->drawPoint((int)(x 0.5), (int)(y 0.5));
x = dx;
y = dy;
}
}
void MainWindow::BresenhamCircle(QPainter* painter, int x, int y, int r)
{
int edgeX,edgeY,p;
edgeX=0;
edgeY=r;
p=3-2*r;
for(;edgeX<=edgeY;edgeX )
{
painter->drawPoint(x edgeX,y edgeY);
double dT=0;
for(int dTNC=1;dTNC<8;dTNC )
{
dT=dTNC*0.25*Pi;
painter->drawPoint( x r*cos(acos(edgeX/double(r)) dT), y r*sin(asin(edgeY/double(r)) dT) );
}
if(p>=0)
{
p =4*(edgeX-edgeY) 10;
edgeY--;
}
else
p =4*edgeX 6;
}
}
void MainWindow::Polygon(QPainter* painter, vector<Pos> cpolygon)
{
if(cpolygon.size()<=1)
return;
vector<Pos>::iterator prevPoint = cpolygon.begin();
for(vector<Pos>::iterator it=cpolygon.begin() 1;it!=cpolygon.end();it ,prevPoint )
{
DDALine(painter,prevPoint->x,prevPoint->y,it->x,it->y);
}
DDALine(painter,prevPoint->x,prevPoint->y,cpolygon.begin()->x,cpolygon.begin()->y);
//fill------------------------------
int imgWidth=img.width();
int imgHeight=img.height();
int x1=rect().left();
int x2=rect().right();
int y1=rect().bottom();
int y2=rect().top();
bool mask[MAXHEIGHT][MAXWIDTH];
for(int y=y1;y<=y2;y )
for(int x=x1;x<=x2;x )
mask[y][x]=false;
for(vector<Pos>::const_iterator it=cpolygon.cbegin();it!=cpolygon.cend();it )
{
int xs=it->x;
int dxs=((it 1)->x-it->x)/((it 1)->y/it->y);
int dys=abs((it 1)->y-it->y)/((it 1)->y-it->y);
for(int ys=it->y;ys!=(it 1)->y;ys =dys)
{
int Ixs=int(xs 0.5);
mask[ys][Ixs]=!mask[ys][Ixs];
xs =dys*dxs;
}
}
QPen initialPen = painter->pen();
for(int y=y1;y<=y2;y )
{
bool inside=false;
for(int x=x1;x<=x2;x )
{
if(mask[y][x])
inside=!inside;
if(inside)
{
painter->setPen(img.pixel(x%imgWidth,y%imgHeight));
painter->drawPoint(x,y);
}
}
}
painter->setPen(initialPen);
//----------------------------------
}
在mainwindow.cpp的最后一個函式Polygon()中,當“fill”部分存在時,當actionDrawPolygon被觸發時程式會崩潰,我點擊滑鼠左鍵(所以mousePressEvent()被呼叫),程式贏了沒有這部分就不會崩潰。
但是當我在這部分添加 printf("TEST") 函式時,沒有列印"TEST",所以這部分根本沒有執行,那為什么會導致程式崩潰呢?
作業系統版本:macOS Monterey 12.0.1
IDE:CLion 2021.2.3
uj5u.com熱心網友回復:
如前所述,您有一個大小bool合適的本地陣列std::sizeof(bool) * MAXHEIGHT * MAXWIDTH。取決于sizeofbool,大小大于 30 兆位元組。
由于堆疊大小有限(可能從 1 兆位元組到通常為 8 兆位元組),程式堆疊將無法處理該大小的陣列。
相反,試試這個:
std::vector<std::vector<bool>> mask(MAXHEIGHT, std::vector<bool>(MAXWIDTH));
這也消除了for將陣列條目初始化為 的回圈的需要false,因為無論如何這將是默認值。
這不是最好的方法,因為它是向量的向量,但是這很可能會繞過您現在看到的崩潰。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/369255.html
