const QSerialPortInfo* serialPortInfo = nullptr;
bool PortManager::setPort(QString portName) {
const QList<QSerialPortInfo> infoList = QSerialPortInfo::availablePorts();
for (const QSerialPortInfo portInfo : infoList) {
if (portInfo.portName() == portName && serialPortInfo != &portInfo) {
serialPortInfo = &portInfo;
}
}
if (serialPortInfo != nullptr) {
if (portName != "" && serialPortInfo->isValid()) { //segmentation fault
if (serialPort->isOpen()) {
serialPort->close();
}
serialPort = new QSerialPort(*serialPortInfo, this);
if (serialPort->open(QIODevice::ReadWrite)) {
if (serialPort->clear()) {
if (serialPort->setBaudRate(QSerialPort::Baud38400, QSerialPort::AllDirections)
&& serialPort->setFlowControl(QSerialPort::NoFlowControl)
&& serialPort->setParity(QSerialPort::NoParity)) {
isPortSet = true;
}
.
.
.
这是我的代码,在Linux和Windows 7上都可以工作。现在我正在Windows 8上测试它,我在此->serialPortInfo->isValid()(以及serialPortInfo的任何其他函数)上得到分段错误。任何特定的QSerialPortInfo对象的所有数据都是"不可用的"(如调试器所述),这在我看来,我没有一些特权来使用它们。在Linux上,我必须是uupc(如果我没记错的话)组的成员才能没有这样的错误,但在Windows 7上,我不需要做任何事情。我运行Qt Creator"作为管理员",但它没有帮助;也许我还得告诉它以管理员身份运行qmake ?但这只是我的猜测,也许原因不同…
问题在于这个循环:
for (const QSerialPortInfo portInfo : infoList) {
if (portInfo.portName() == portName && serialPortInfo != &portInfo) {
serialPortInfo = &portInfo;
}
}
变量portInfo
的作用域仅在循环内部,且仅适用于当前迭代。一旦循环迭代,该变量将被销毁。使用指向解构对象的指针是未定义的行为,并且可能导致崩溃。
我给你的建议是不要使用指针。
这是一个典型的例子,说明当你不打算改变内容时,Qt鼓励你在for循环中使用const引用。请看这一行:
for (const QSerialPortInfo portInfo : infoList) {
你应该这样写,让它工作:
for (const QSerialPortInfo &portInfo : infoList) {
// ^
原因很简单,你是在创建一个临时副本,当超出作用域时,它会被销毁,而不是使用原始列表项,因为原始列表项在循环之外,因此会超时。
你一定很高兴它在Linux和Windows 7上都能工作。我对此感到非常惊讶,即使它真的发生了,它也可能在某个特定时刻向你的客户爆炸。
话虽如此,你的概念似乎总体上是错误的。查询所有项,找到一个专用端口。首先,像这样构造QSerialPortInfo实例会更清晰:
serialPortInfo = new QSerialPortInfo(portName);
此外,您确实应该使用堆栈对象而不是堆。这样的信息类不应该在堆上分配,特别是在没有智能指针管理的情况下。
毋庸置疑,当全局变量是邪恶的时候,创建全局变量是不好的,尤其是在这种情况下,你可以通过将其放入方法本身来避免它。
如果停止使用指针,也可以去掉下面一行:
if (serialPortInfo != nullptr) {
更不用说,在Qt应用程序中,无论如何都应该使用Q_NULLPTR,因为这在没有c++ 11支持的情况下也可以工作,同样的原因也适用于原始的for循环。我会使用Qt中的foreach,但话说回来,我认为整体概念是错误的。
似乎您甚至不需要QSerialPortInfo
实例,因为您所使用的只是您可以直接传递给QSerialPort
对象的名称。因此,您甚至可以去掉QSerialPortInfo
对象。
因此,我建议将for循环和QSerialPortInfo
实例一起删除,直接在方法中使用QSerialPort
。