最近编写一个大项目中的某个设置窗口,结果出了一BUG,调了半天没调对,部分代码如下:
CGetSetDataWidget::CGetSetDataWidget(SSetDataStruct *setData, QWidget *parent, Qt::WFlags flags)
: QWidget(parent, flags)
{
......
connect(layerPushButton, SIGNAL(clicked()), this, SLOT(clickedLayerPushButton()));
connect(faultPushButton, SIGNAL(clicked()), this, SLOT(clickedFaultPushButton()));
connect(okButton, SIGNAL(clicked()), this, SLOT(clickedOkButton()));
connect(xLineEdit, SIGNAL(textChanged ( const QString &)), this, SLOT(changedxLineText(const QString &)));
connect(inLineEdit, SIGNAL(textChanged ( const QString &)), this, SLOT(changedinLineText(const QString &)));
......
xLineEdit->setText(QApplication::translate("Settings", "100", 0, QApplication::UnicodeUTF8));
inLineEdit->setText(QApplication::translate("Settings", "100", 0, QApplication::UnicodeUTF8));
m_setData = setData;
m_setData->layerFile = "";
m_setData->faultFile = "";
m_setData->max_xLine = 100;
m_setData->max_inLine = 100;
}
void CGetSetDataWidget::changedxLineText(const QString &text)
{
bool ok;
unsigned int xMax = text.toUInt(&ok, 10);
if ( ok == false || xMax == 0 )
{
m_setData->max_xLine = 100;
return;
}
m_setData->max_xLine = xMax;
}
结果运行时出现地址访问错误,Debug一下,发现变量m_setData地址指针错误。开始以为是参数传递错误,所以将:
m_setData = setData;
改为:
m_setData = new SSetDataStruct;
结果错误依旧。
最后用分步运行,发现类CGetSetDataWidget初始化时,下列语句被跳过:
m_setData = setData;
m_setData->layerFile = "";
m_setData->faultFile = "";
m_setData->max_xLine = 100;
m_setData->max_inLine = 100;
那么问题出在哪里了?我发现在程序运行到
xLineEdit->setText(QApplication::translate("Settings", "100", 0, QApplication::UnicodeUTF8));
时,直接跳过下面的语句,执行了changedxLineText(const QString &text)槽函数,也就是说,我们期待的
m_setData = setData;
这条赋值语句并没有被执行,指针变量m_setData当然没有值。
那么为什么会这样呢?在类初始化时,我们将xLineEdit的文本改变信号与槽函数changedxLineText(const QString &text)链接起来:
connect(xLineEdit, SIGNAL(textChanged ( const QString &)), this, SLOT(changedxLineText(const QString &)));
当xLineEdit执行setText操作时,就触发了textChanged ( const QString &)信号,结果转到相应的槽函数执行,这时由于指针变量m_setData没有初始化,其赋值操作当然会导致内存错误。
原因搞明白了,那么解决办法就很简单了,只要将:
m_setData = setData;
这条语句调到xLineEdit->setText(...)之前就行,为了避免发生类似错误,一般把赋值语句放在connect()函数之前。
该问题现在想起来很弱智,但是却告诉我们,在编写程序时,赋值语句的顺序是不容忽视的,很多时候,错误的代码顺序并不会产生编译错误,但是一旦程序运行,很可能产生大量未知错误,将花费我们大量的时间去调试。