PDA

View Full Version : Block Type invalid Assertion when running SerialPortInfo in foreach snippet



davethomaspilot
23rd November 2012, 01:12
I'm "kicking the tires" on QtSerialPort.

The Qt docs have this simple code fragment as an example of how to use SerialPortInfo:

// Example use SerialPortInfo
foreach (const SerialPortInfo &info, SerialPortInfo::availablePorts()) {
qDebug() << "Name : " << info.portName();
qDebug() << "Description : " << info.description();
qDebug() << "Manufacturer: " << info.manufacturer();

// Example use SerialPort
SerialPort serial;
serial.setPort(info);
if (serial.open(QIODevice::ReadWrite))
serial.close();
}

When I run the code, the loop runs once, and does the qDebug print. But, I get an exception when stepping out of the loop (at the curly brace).

I commented out nearly everything, and still get the exception:

int _tmain(int argc, _TCHAR* argv[])
{
QApplication app(argc, argv);
app.setOrganizationName("Flying Nerd");

app.setApplicationName("Stats Helpwer");

// MainWindow mainWin;
//mainWin.show();
//mainWin.raise();

// Example use SerialPortInfo
foreach (const SerialPortInfo &info, SerialPortInfo::availablePorts()) {
qDebug() << "Name : " << info.portName();
qDebug() << "Description : " << info.description();
qDebug() << "Manufacturer: " << info.manufacturer();

// Example use SerialPort
//SerialPort serial;
//serial.setPort(info);
//if (serial.open(QIODevice::ReadWrite))
// serial.close();
}

return app.exec();

}

I haven't been able to build the docs for QtSerialPort class either. If I knew what SerialPortInfo::availablePorts returns (a container of some sort for SerialPortInfo &, I'm thinking), I'd try avoiding use of the foreach and just iterate through the items in the container.

So, two questions:

1) Is there class documentation online somewhere for the QtSerialPort classes (if not, I'll struggle more with building the docs).
2) Anybody spot why I'm getting the exception?

Thanks,

Dave Thomas

kuzulis
23rd November 2012, 15:42
@davethomaspilot



1) Is there class documentation online somewhere for the QtSerialPort classes (if not, I'll struggle more with building the docs).


No, the final documentation anywhere yet.
On the WiKi (http://qt-project.org/wiki/QtSerialPort) written How To generate documentation.



2) Anybody spot why I'm getting the exception?


I do not know, use "enumerator" or "cenumerator" example from /examples .

amleto
23rd November 2012, 18:51
what happens if you change to


...
SequenceType sequence = SerialPortInfo::availablePorts();

foreach (const SerialPortInfo &info, sequence) {

Obviously you have to change SequenceType to whatever it is meant to be.

davethomaspilot
23rd November 2012, 23:56
@davethomaspilot



No, the final documentation anywhere yet.
On the WiKi (http://qt-project.org/wiki/QtSerialPort) written How To generate documentation.



I do not know, use "enumerator" or "cenumerator" example from /examples .


Yes, I saw the How to generate documentation. But, it didn't work until I deleted a line in serialport.qdocconf which referenced $QT5. Once I got the class docs generated, I see that availablePorts() returns a QList<SerialPortInfo>.

So, I avoided use of the foreach by using an iterator works:

int _tmain(int argc, _TCHAR* argv[])
{
QApplication app(argc, argv);
app.setOrganizationName("Flying Nerd");

app.setApplicationName("Stats Helpwer");

QList<SerialPortInfo> ports;
ports = SerialPortInfo::availablePorts();

QList<SerialPortInfo>::iterator i;
for (i = ports.begin(); i != ports.end(); ++i)
{
qDebug() << "Name : " << i->portName();
qDebug() << "Description : " << i->description();
qDebug() << "Manufacturer: " << i->manufacturer();
}

So, I'm not sure what to conclude. I've been using Qt for a few months now, but I wasn't aware of the foreach construct until I saw the example for QtSerialPort. I can see using that all the time--much handier than declaring an iterator and remembering the syntax for looping through using the iterator.

The build instructions on

http://qt-project.org/wiki/QtSerialPort

don't quite match the source tree it references. So, while I got things to build, maybe I didn't do something quite right. The build instructions that are in the source tree are incomplete--they just say (literally) BLAH, BLAH, BLAH.

Thanks,

Dave Thomas

Added after 4 minutes:


what happens if you change to


...
SequenceType sequence = SerialPortInfo::availablePorts();

foreach (const SerialPortInfo &info, sequence) {

Obviously you have to change SequenceType to whatever it is meant to be.

That works!

So what does it mean?

Thanks,

Dave Thomas

davethomaspilot
24th November 2012, 13:46
Actually, not the assertion occurs when returning from main() instead of when exiting the foreach block.


int _tmain(int argc, _TCHAR* argv[])
{
QApplication app(argc, argv);
app.setOrganizationName("Flying Nerd");

app.setApplicationName("Stats Helpwer");

QList<SerialPortInfo> ports;
ports = SerialPortInfo::availablePorts();


MainWindow mainWin;
mainWin.show();
mainWin.raise();
#if 1
// Example use SerialPortInfo
foreach (const SerialPortInfo &info,ports ) {
qDebug() << "Name : " << info.portName();
qDebug() << "Description : " << info.description();
qDebug() << "Manufacturer: " << info.manufacturer();

// Example use SerialPort
SerialPort serial;
serial.setPort(info);
if (serial.open(QIODevice::ReadWrite))
serial.close();
}
#endif
return app.exec();

}

The assertion occurs in a delete in the SerialPort destructor.

I'm going to try just creating then deleting a QList of SerialPortInfo

Dave Thomas

amleto
24th November 2012, 14:41
means there is a bug in SerialPortInfo dtor...

davethomaspilot
25th November 2012, 00:54
The destructor is empty:

/*!
Destroys the SerialPortInfo object. References to the values in the
object become invalid.
*/
SerialPortInfo::~SerialPortInfo()
{
}

The code snippet with a SerialPortInfo is used in the console example also.

Dave Thomas

Added after 44 minutes:

This is sufficient to cause the assertion to occur:



QList<SerialPortInfo> ports;
ports = SerialPortInfo::availablePorts();

delete &ports;


The assertion does NOT occur if I use the debug version of the SerialPort lib.

So, I have my "workaround".

kuzulis
25th November 2012, 18:13
So, in the end, how me reproduce the problem to try fix it?
Give me brief step by step detailed information.

davethomaspilot
25th November 2012, 20:02
So, in the end, how me reproduce the problem to try fix it?
Give me brief step by step detailed information.

Just create a Qlist of SeriaPortInfo then delete it:



This is sufficient to cause the assertion to occur:


QList<SerialPortInfo> ports;
ports = SerialPortInfo::availablePorts();

delete &ports;

The assertion does NOT occur if I use the debug version of the SerialPort lib.

Or, define the list as an local variable. When it goes out of scope, the assertion occurs.

Dave Thomas

amleto
26th November 2012, 04:26
The destructor is empty:

/*!
Destroys the SerialPortInfo object. References to the values in the
object become invalid.
*/
SerialPortInfo::~SerialPortInfo()
{
}

The code snippet with a SerialPortInfo is used in the console example also.

Dave Thomas

Added after 44 minutes:

This is sufficient to cause the assertion to occur:




The assertion does NOT occur if I use the debug version of the SerialPort lib.

So, I have my "workaround".

that is NOT valid c++!! you shouldn't 'delete' stack variables!




void test()
{
{
QList<SerialPortInfo> ports;
ports = SerialPortInfo::availablePorts();
}
}
that is better.

are you mixing debug and release object code/libraries when testing this new class?

kuzulis
26th November 2012, 08:24
I'm can not reproduce problem:



#include <QCoreApplication>
#include <QDebug>

#include <serialportinfo.h>


QT_USE_NAMESPACE_SERIALPORT

void test()
{
{
QList<SerialPortInfo> ports;
ports = SerialPortInfo::availablePorts();

foreach (const SerialPortInfo &info, ports)
qDebug() << info.portName();
}
}

int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

test();

return a.exec();
}


Qt 4.8.3 + MinGW4.4 -> release build

davethomaspilot
26th November 2012, 13:53
That causes the assertion for me.

Qt 4.8.2 debug dlls, but SerialPort1.lib.

When I use SerialPortd1.lib, the issue goes away.


On the stack frame, there is a message 'scalar deleting destructor'().

Let me know how I can help.

Dave Thomas

amleto
26th November 2012, 14:22
right, so there is no problem then - just you using the wrong lib version

davethomaspilot
26th November 2012, 16:53
Shouldn't both the debug and non-debug version of the lib work?

amleto
26th November 2012, 16:57
Are you serious? You cant mix up debug and non debug libs. So no, the release version shouldnt work if the rest of your app is debug version

davethomaspilot
3rd December 2012, 13:52
Yes, I was serious.

Sorry for my stupidity. On *nix systems, we didn't have libs, and often mixed both debug and non-debug versions of dlls. I just assumed same would apply for windows.

What a pain, to have to have both versions of ALL the binaries just to debug my relatively tiny application? But, another discussion, I know.

Thanks!

Dave Thomas

amleto
3rd December 2012, 15:29
you shouldn't mix debug & release libs/dlls on *nix either.

And you don't need release versions to debug your app...

davethomaspilot
3rd December 2012, 15:44
you shouldn't mix debug & release libs/dlls on *nix either.

Why not? One approach is to have the release's text section(code) to be identical so the only difference is the absence of debug data. This is a good approach where the binary size is important, but performance optimization is not worth the associated hassles.

So,for libraries we always use non-debug dll's and always used binaries with debug data for the code we developed. We rarely needed to step into the library code but we needed the debug data until release time.

Frequently, we wouldn't even turn on optimization for the release builds--just strip the debug data.

"And you don't need release versions to debug your app.."

You do if the debug versions won't fit in the space you have in your embedded application.

Thanks,

Dave Thomas

amleto
3rd December 2012, 18:05
why? because you do not have a guarantee that the CRTs are compatible.