QtSerialPort有不可用的数据,分割故障仅在Windows 8下


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

相关内容

  • 没有找到相关文章

最新更新