I am rather new to Qt, maybe that's why I cant fully understand the child-parent concept. I need to perform some sql query. I set the QSqlQuery, perform the "prepare and bind" operation and exec it. Next I pass it to the model and display the data. The problem occurs when closing the window - I get a memory violation error. The error occurs only, when I create the model with a parent. Here's the code:
QSqlQuery query;
query.prepare(QString("SELECT \
%1 as nazwa \
, kontrahentid \
FROM kontrahent WHERE %2 ilike ?"
).arg(showWhat, searchBy) //handled above, no need to escape
);
query.addBindValue(searchString); //user input data - so bind it
if (!query.exec()) {
qDebug() << query.lastError();
QApplication::restoreOverrideCursor();
return;
}
if (model == NULL)
// model = new QSqlQueryModel; // app closes the window correctly
model = new QSqlQueryModel(this); // app crashes when closing the window
model->setQuery(query);
if (model->lastError().isValid()) {
qDebug() << model->lastError();
QApplication::restoreOverrideCursor();
return;
}
model->setHeaderData(0, Qt::Horizontal, "ID");
ui.kontrahenciList->setModel(model);
//ui.kontrahenciList->setModelColumn(1);
ui.kontrahenciList->show();
Here's the error I'm getting:
Unhandled exception at 0x0fe29f9a (qsqlpsqld.dll) in HurBudClientGUI.exe: 0xC0000005: Access violation reading location 0x00000004.
and the call stack:
qsqlpsqld.dll!QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> >::data() Line 143 + 0x3 bytes C++
qsqlpsqld.dll!qGetPtrHelper<QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> > >(const QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> > & p) Line 919 + 0xb bytes C++
qsqlpsqld.dll!QPSQLDriver::d_func() Line 106 + 0x13 bytes C++
qsqlpsqld.dll!QPSQLResultPrivate::privDriver() Line 212 C++
qsqlpsqld.dll!QPSQLResultPrivate::deallocatePreparedStmt() Line 306 + 0xc bytes C++
qsqlpsqld.dll!QPSQLResult::~QPSQLResult() Line 328 C++
qsqlpsqld.dll!QPSQLResult::`scalar deleting destructor'() + 0xf bytes C++
Qt5Sqld.dll!QSqlQueryPrivate::~QSqlQueryPrivate() Line 94 + 0x23 bytes C++
Qt5Sqld.dll!QSqlQueryPrivate::`scalar deleting destructor'() + 0xf bytes C++
Qt5Sqld.dll!QSqlQuery::~QSqlQuery() Line 245 + 0x1e bytes C++
Qt5Sqld.dll!QSqlQueryModelPrivate::~QSqlQueryModelPrivate() Line 90 + 0x3d bytes C++
Qt5Sqld.dll!QSqlQueryModelPrivate::`scalar deleting destructor'() + 0xf bytes C++
Qt5Cored.dll!672cbf06()
[Frames below may be incorrect and/or missing, no symbols loaded for Qt5Cored.dll]
Qt5Cored.dll!672cb92a()
Qt5Cored.dll!672c03f4()
Qt5Cored.dll!67200dc4()
Qt5Cored.dll!67203608()
Qt5Sqld.dll!QSqlQueryModel::~QSqlQueryModel() Line 175 + 0x9 bytes C++
As I mentioned above: the error doesn't happen when (one of below):
I create QSqlQueryModel without the parent (model = new QSqlQueryModel;)
I pass "static" query to QSqlQueryModel (regardless of having the parent).
eg:
model->setQuery(
QSqlQuery(
QString("SELECT \
%1 as nazwa \
, kontrahentid \
FROM kontrahent"
).arg(showWhat)
)
);
What am I doing wrong?
And the real question is: what is the purpose for QSqlQueryModel having a parent? If I delete it manually in the window's destructor - is there any diffrence?
I guess this is a bug - I reported it on qt bugtracker:
https://bugreports.qt.io/browse/QTBUG-43889
This is the key part:
if (model == NULL)
// model = new QSqlQueryModel; // app closes the window correctly
model = new QSqlQueryModel(this); // app crashes when closing the window
The parent-child concept in Qt provides many features, with automatic child destruction being one of them.
If any QObject has other QObject set as a parent, then when parent QObject is deleted, the child object will also be deleted.
Now, you mentioned you do explicitly delete the model in destructor of the window. You should not. If you define this as a parent, then the model will be automatically deleted together with this, but it was already deleted by you in the destructor, so model is deleted twice, thus your error appears.
So I removed the "delete operation" code in the destructor. Error still occurs, the only difference is diffrent call stack.
error message:
Unhandled exception at 0x0f249f9a (qsqlpsqld.dll) in HurBudClientGUI.exe: 0xC0000005: Access violation reading location 0x00000004.
call stack:
qsqlpsqld.dll!QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> >::data() Line 143 + 0x3 bytes C++
qsqlpsqld.dll!qGetPtrHelper<QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> > >(const QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> > & p) Line 919 + 0xb bytes C++
qsqlpsqld.dll!QPSQLDriver::d_func() Line 106 + 0x13 bytes C++
qsqlpsqld.dll!QPSQLResultPrivate::privDriver() Line 212 C++
qsqlpsqld.dll!QPSQLResultPrivate::deallocatePreparedStmt() Line 306 + 0xc bytes C++
qsqlpsqld.dll!QPSQLResult::~QPSQLResult() Line 328 C++
qsqlpsqld.dll!QPSQLResult::`scalar deleting destructor'() + 0xf bytes C++
Qt5Sqld.dll!QSqlQueryPrivate::~QSqlQueryPrivate() Line 94 + 0x23 bytes C++
Qt5Sqld.dll!QSqlQueryPrivate::`scalar deleting destructor'() + 0xf bytes C++
Qt5Sqld.dll!QSqlQuery::~QSqlQuery() Line 245 + 0x1e bytes C++
Qt5Sqld.dll!QSqlQueryModelPrivate::~QSqlQueryModelPrivate() Line 90 + 0x3d bytes C++
Qt5Sqld.dll!QSqlQueryModelPrivate::`scalar deleting destructor'() + 0xf bytes C++
Qt5Cored.dll!QScopedPointerDeleter<QObjectData>::cleanup(QObjectData * pointer) Line 62 + 0x20 bytes C++
Qt5Cored.dll!QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> >::~QScopedPointer<QObjectData,QScopedPointerDeleter<QObjectData> >() Line 109 + 0x9 bytes C++
Qt5Cored.dll!QObject::~QObject() Line 940 + 0x15 bytes C++
Qt5Cored.dll!QAbstractItemModel::~QAbstractItemModel() Line 1454 + 0xf bytes C++
Qt5Cored.dll!QAbstractTableModel::~QAbstractTableModel() Line 3299 + 0x8 bytes C++
Qt5Sqld.dll!QSqlQueryModel::~QSqlQueryModel() Line 175 + 0x9 bytes C++
HurBudClientGUI.exe!QSqlQueryModel::`scalar deleting destructor'() + 0x10 bytes C++
Qt5Cored.dll!QObjectPrivate::deleteChildren() Line 1841 + 0x24 bytes C++
Qt5Widgetsd.dll!QWidget::~QWidget() Line 1488 C++
Qt5Widgetsd.dll!QDockWidget::~QDockWidget() Line 1172 + 0x22 bytes C++
HurBudClientGUI.exe!searchDock::~searchDock() Line 28 + 0x1c bytes C++
searchDock is the class I'm working with.
I guess I solved it. When the model is initialized as view's child:
model = new QSqlQueryModel(this);
The problem is order of operations. When I close the connection and remove the database in the destructor of my class - the database gets disconnected and no further operations are possible. But after my class' destructor, destructors of its base classes get into action - one by another, as ordered by inheritance. When QObject::~QObject() is executed, it gets to the
QObjectPrivate::deleteChildren()
method. And then, it finally gets to delete the model. The model wants to free the resources - which means QSqlResult (QPSQLResult to be specific in that case). This it how it looks:
QPSQLResult::~QPSQLResult()
{
Q_D(QPSQLResult);
cleanup();
if (d->preparedQueriesEnabled && !d->preparedStmtId.isNull())
d->deallocatePreparedStmt();
};
So here Qt tries to deallocate preparedStatement - regardless of the fact, that the connection no longer exists:
void QPSQLResultPrivate::deallocatePreparedStmt()
{
const QString stmt = QLatin1String("DEALLOCATE ") + preparedStmtId;
PGresult *result = privDriver()->exec(stmt);
if (PQresultStatus(result) != PGRES_COMMAND_OK)
qWarning("Unable to free statement: %s", PQerrorMessage(privDriver()->connection));
PQclear(result);
preparedStmtId.clear();
};
So - to make it work properly, I wolud have to call
QSqlQueryModel::~QSqlQueryModel()
or
QSqlQueryModel::clear()
BEFORE closing the connection with the DB. I still think it's a bug.
Related
I'm new to NS3 and i was trying to extract ip address of a packet from QueueDiscItem,
when i have:
Ptr< QueueDiscItem > item initiated and call:
item->Print(std::cout);
the output i get is
"tos 0x0 DSCP Default ECN Not-ECT ttl 63 id 265 protocol 6 offset (bytes) 0 flags [none] length: 76 10.1.4.2 > 10.1.2.1 0x7fffc67ec880 Dst addr 02-06-ff:ff:ff:ff:ff:ff proto 2048 txq"
but when i call:
Ipv4Header header;
item->GetPacket()->PeekHeader(header);
header.Print(std::cout);
the output i get is
"tos 0x0 DSCP Default ECN Not-ECT ttl 0 id 0 protocol 0 offset (bytes) 0 flags [none] length: 20 102.102.102.102 > 102.102.102.102"
How to get the Header data
According to the list of TraceSources, the TraceSources associated with QueueDiscItems are for Queues. I'm guessing you were trying to attach to one of those TraceSources.
A QueueDiscItem encapsulates several things: a Ptr<Packet>, a MAC address, and several more things. Since you are using IPv4, the QueueDiscItem is actually an Ipv4QueueDiscItem (the latter is a subclass of the former). So, let's start by casting the QueueDiscItem to an Ipv4QueueDiscItem by
Ptr<const Ipv4QueueDiscItem> ipItem = DynamicCast<const Ipv4QueueDiscItem>(item);
Next, you need to know that at this point in the simulation, the Ipv4Header has not been added to the Ptr<Packet> yet. This is probably a design choice (that I don't understand). So, how can we get this information? Well, the Ipv4QueueDiscItem encapsulates the Ipv4Header, and at some point before passing the Ptr<Packet> to L2, the header is added to the packet. This Header can be retrieved by
const Ipv4Header ipHeader = ipItem->GetHeader();
So, now we have the Ipv4Header of the packet you're interested in. Now, we can safely get the address from the Ipv4QueueDiscItem by
ipHeader.GetSource();
ipHeader.GetDestination();
In summary, your TraceSource function should look something like this:
void
EnqueueTrace (Ptr<const QueueDiscItem> item) {
Ptr<const Ipv4QueueDiscItem> ipItem = DynamicCast<const Ipv4QueueDiscItem>(item);
const Ipv4Header ipHeader = ipItem->GetHeader();
NS_LOG_UNCOND("Packet received at " << Simulator::Now() << " going from " << ipHeader.GetSource() << " to " << ipHeader.GetDestination());
}
Why does item->Print(std::cout); work?
All of the above makes sense, but why does
item->Print(std::cout);
print the correct addresses? First, it is important to realize that here Print() is a function of the QueueDiscItem, not the Packet. If we go to the source of this function, we find that Print() just prints the Header if it has already been added.
After reading https://www.quora.com/How-can-I-bypass-the-OS-buffering-during-I-O-in-Linux I want to try to access data on the serial port with the O_DIRECT option, but the only way I can seem to do that is by adding the GNU_SOURCE define but when I tried to execute the program, nothing at all is printed on the screen.
If I remove "#define _GNU_SOURCE" and compile, then the system gives me an error on O_DIRECT.
If I remove the define and the O_DIRECT flag, then incorrect (possibly outdated) data is always read, but the data is printed on the screen.
I still want to use the O_DIRECT flag and be able to see the data, so I feel I need an alternative command to printf and friends, but I don't know how to continue.
I attached the code below:
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include <unistd.h>
#include <termios.h>
#define TIMEOUT 5
int main(){
char inb[3]; //our byte buffer
int nread=0; //number bytes read from port
int n; //counter
int iosz=128; //Lets get 128 bytes
int fd=open("/dev/ttyS0", O_NOCTTY | O_RDONLY | O_SYNC | O_DIRECT); //Open port
tcflush(fd,TCIOFLUSH);
for(n=0;n<iosz;n++){
int s=time(NULL); //Start timer for 5 seconds
while (time(NULL)-s < TIMEOUT && nread < 1){
inb[0]='A'; //Fill buffer with bad data
inb[1]='B';
inb[2]='C';
nread=read(fd,(char*)inb,1); //Read ONE byte
tcflush(fd,TCIOFLUSH);
if (nread < 0 || time(NULL)-s >= TIMEOUT){
close(fd); //Exit if read error or timeout
return -1;
}
}
printf("%x:%d ",inb[0] & 0xFF,nread); //Print byte as we receive it
}
close(fd); //program ends so close and exit
printf("\n"); //Print byte as we receive it
return 0;
}
First off, I'm no expert on this topic, just curious about it, so take this answer with a pinch of salt.
I don't know if what you're trying to do here (if I'm not looking at it the wrong way it seems to be to bypass the kernel and read directly from the port to userspace) was ever a possibility (you can find some examples, like this one but I could not find anything properly documented) but with recent kernels you should be getting an error running your code, but you're not catching it.
If you add these lines after declaring your port:
...
int fd=open("/dev/ttyS0", O_NOCTTY | O_RDONLY | O_SYNC | O_DIRECT );
if (fd == -1) {
fprintf(stderr, "Error %d opening SERIALPORT : %s\n", errno, strerror(errno));
return 1;
}
tcflush(fd,TCIOFLUSH);
....
When you try to run you'll get: Error 22 opening SERIALPORT : Invalid argument
In my humble and limited understanding, you should be able to get the same effect changing the settings on termios to raw, something like this should do:
struct termios t;
tcgetattr(fd, &t); /* get current port state */
cfmakeraw(&t); /* set port state to raw */
tcsetattr(fd, TCSAFLUSH, &t); /* set updated port state */
There are many good sources for termios, but the only place I could find taht also refers to O_DIRECT (for files) is this one.
Is there a way to do a single read() in non-blocking mode on a pipe/terminal/etc, the way I can do it on a socket with recv(MSG_DONTWAIT)?
The reason I need that is because I cannot find any guarantee that a read() on a file-descriptor returned as ready for reading by select() or poll() will not block.
I know can make the file descriptor non-blocking with fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK) but this will change the mode on that file descriptor globally, not just in the calling thread/process. For example:
% perl -MFcntl=F_SETFL,F_GETFL,O_NONBLOCK -e 'fcntl STDIN, F_SETFL, fcntl(STDIN, F_GETFL, 0) | O_NONBLOCK; select undef, undef, undef, undef'
^Z # put it in the background
% cat
cat: -: Resource temporarily unavailable
This will also make the fd non blocking for both reading and writing, which may confuse the hell out of another process doing the opposite on the same fd, as in:
non_blocking_read | filter | blocking_write
One way I think of is to save the file status flags on starting up and SIGCONT, and restore them on exiting and on SIGTSTP (just the way it's done with the termios settings), but this is very limited, race-prone, and will leave a mess behind in the case where the program exited abnormally.
Putting a save/restore with fcntl() before/after each read() also feels ugly and dumb, and may have other issues too. The same with an ioctl(FIONREAD) just before the read (which I'm not even sure it will work reliably with any fd; assurances in that direction will be welcome, though).
I would be happy even with system specific (eg. linux or bsd-only) solutions.
For reference, here is a discussion about fixing it in linux; the idea didn't seem to get anywhere, though.
A Linux only solution would be to reopen the file descriptor via
"/dev/stdin"|"/dev/tty"|"/dev/fd/$fd".
C example:
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
int main()
{
int fd;
char buf[8];
int flags;
if(0>(fd=open("/dev/stdin", O_RDONLY))) return 1;
if(0>(flags = fcntl(fd,F_GETFL))) return 1;
if(0>(flags = fcntl(fd,F_SETFL,flags|O_NONBLOCK))) return 1;
sleep(3);
puts("reading");
ssize_t nr = read(fd, buf, sizeof(buf));
printf("read=%zd\n", nr);
return 0;
}
Unlike a duplicated file descriptor, a reopened filedescriptor will have independent file status flags.
I am experimenting with Vivante GPU GC2000 Series, where the clinfo produced the below result.
CL_DEVICE_GLOBAL_MEM_SIZE: 64 MByte
CL_DEVICE_MAX_MEM_ALLOC_SIZE: 32 MByte
CL_DEVICE_GLOBAL_MEM_CACHE_TYPE: Read/Write
CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE: 64
CL_DEVICE_GLOBAL_MEM_CACHE_SIZE: 4096
CL_DEVICE_LOCAL_MEM_SIZE: 1 KByte
CL_DEVICE_LOCAL_MEM_TYPE: Global
CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE: 4 KByte
CL_DEVICE_MAX_CONSTANT_ARGS: 9
From above output, it is clear that 64MByte is the limit for Global Memory allocation.
Now, when I tried allocating 900Mbytes global size, i have not received any error and it is successful.
int noOfBytes = (900 * 1024 * 1024);
memPtr = clCreateBuffer(context, CL_MEM_READ_WRITE, noOfBytes, NULL, &err);
if ( err != CL_SUCESS) {
printf ("Ooops.. Failed");
}
Sounds this experiment is show proving what the clinfo claims. Am i missing any theory or something else ?
Because buffers and images are allocated on an OpenCL context (not an OpenCL device) the actual device allocation is often deferred until the buffer is used on a specific device. So while this allocation seemed to work, if you try to actually use that buffer on your device, you'll get an error.
I'm trying to use the internal flash of an STM32F405 to store a bunch of user settable bytes that remain after rebooting.
I'm using:
uint8_t userConfig[64] __attribute__((at(0x0800C000)));
to allocate memory for the data I want to store.
When the program starts, I check to see if the first byte is set to 0x42, if not, i set it using:
HAL_FLASH_Unlock();
HAL_FLASH_Program(TYPEPROGRAM_BYTE, &userConfig[0], 0x42);
HAL_FLASH_Lock();
After that I check the value in userConfig[0] and I see 0x42... Great!
When I hit reset, however, and look at the location again, it's not 0x42 anymore...
Any idea where I'm going wrong? I've also tried:
#pragma location = 0x0800C00
volatile const uint8_t userConfig[64]
but I get the same result..
Okay I found an answer on the ST forums thanks to clive1. This example works for an STM32F405xG.
First we need to modify the memory layout in the linker script file (.ld file)
Modify the existing FLASH and add a new line for DATA. Here I've allocated all of section 11.
MEMORY
{
FLASH (RX) : ORIGIN = 0x08000000, LENGTH = 1M-128K
DATA (RWX) : ORIGIN = 0x080E0000, LENGTH = 128k
...
...
}
Manual for editing linker files on the sourceware website
In the same file, we need to add:
.user_data :
{
. = ALIGN(4);
*(.user_data)
. = ALIGN(4);
} > DATA
This creates a section called .user_data that we can address in the program code.
Finally, in your .c file add:
__attribute__((__section__(".user_data"))) const uint8_t userConfig[64]
This specifies that we wish to store the userConfig variable in the .user_data section and const makes sure the address of userConfig is kept static.
Now, to write to this area of flash during runtime, you can use the stm32f4 stdlib or HAL flash driver.
Before you can write to the flash, it has to be erased (all bytes set to 0xFF) The instructions for the HAL library say nothing about doing this for some reason...
HAL_FLASH_Unlock();
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP | FLASH_FLAG_OPERR | FLASH_FLAG_WRPERR | FLASH_FLAG_PGAERR | FLASH_FLAG_PGSERR );
FLASH_Erase_Sector(FLASH_SECTOR_11, VOLTAGE_RANGE_3);
HAL_FLASH_Program(TYPEPROGRAM_WORD, &userConfig[index], someData);
HAL_FLASH_Lock();