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上testing它,并在this-> serialPortInfo-> isValid()(以及serialPortInfo的任何其他函数)上出现分段错误。 任何特定的QSerialPortInfo对象的所有数据都是“不可用的”(如debugging器所述),在我看来,我没有一些特权使用它们。 在Linux上,我必须成为uupc的成员(如果我记得正确的话)组没有这样的错误,但在Windows 7上,我不必做任何事情。 我运行Qt Creator“以pipe理员身份”,但没有帮助; 也许我不得不以某种方式告诉它以pipe理员身份运行qmake? 但这只是我的猜测,也许原因是不同的…
这是一个典型的例子,为什么Qt鼓励你在不打算改变内容的时候在循环中使用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
对象的QSerialPort
。 因此,你甚至可以摆脱QSerialPortInfo
对象。
所以,只要将方法内的for循环和QSerialPortInfo
实例共同使用QSerialPort
直接使用QSerialPort
就是我的建议。
问题是这个循环:
for (const QSerialPortInfo portInfo : infoList) { if (portInfo.portName() == portName && serialPortInfo != &portInfo) { serialPortInfo = &portInfo; } }
变量portInfo
的作用域仅在循环内部,仅用于当前迭代。 一旦循环迭代,那个变量就被销毁了。 使用指向被破坏的对象的指针是未定义的行为 ,并可能导致崩溃。
我的建议是关于如何阻止它不使用指针。 而是复制结构。