Error passing pointer in QT - qt

In QT have the following code that starts a thread to send out commands. The thread takes a char * and int as arguments. In the "run" I use the pointer that is given by the constuctor. The code is:
MyThread::MyThread(char * payld, int payld_size)
{
payload_size = payld_size;
payload_p = payld;
}
void MyThread::run()
{
while(...)
{
sendCommand(payload_p, payload_size);
}
}
Unfortunately this doesn´t work and my application crashes when I try to use thread.start(). But when I change it to:
MyThread::MyThread(char * payld, int payld_size)
{
payload_size = payld_size;
payload_p = payld;
for(int i=0; i<payload_size; i++)
{
payload[i] = payld[i];
}
}
void MyThread::run()
{
while(...)
{
sendCommand(payload, payload_size);
}
}
The code does run and only crashes sometimes (looks pretty random to me). Can anybody Explain me why version one doesnt work and version two does? And any ideas on why the second code sometimes crashes? Could it be because the size of payload is not predefined (in the header file I defined it as
char payload[];
When I define it as:
char payload[10];
it seems to work better, but it is annoying to test since the crashes are pretty random.

instead of fiddling with char*, I would switch to QString (since you're using Qt). It takes a bit of learning, but it's almost mandatory to get code working smoothly in this framework. Then declare
QString payload;
and depending on sendCommand implementation, use one of the member functions QString to get the char*, like payload.toLatin1()

Related

How does one call a function from it's memory address in AVR C?

I am writing a function:
void callFunctionAt(uint32_t address){
//There is a void at address, how do I run it?
}
This is in Atmel Studio's C++. If previous questions are to be believed, the simple answer is to write the line "address();". This cannot be correct. Without changing the header of this function, how would one call the function located at the address given?
The answer should be system-agnostic for all micro controllers which support standard c++ compilation.
The common way to do this is to give the argument the correct type. Then you can call it right away:
void callFunctionAt(void (*address)()) {
address();
}
However, since you wrote "Without changing the header of this function [...]", you need to cast the unsigned integer to a function pointer:
void callFunctionAt(uint32_t address) {
void (*f)() = reinterpret_cast<void (*f)()>(address);
f();
}
But this is not safe and not portabel because it assumes that the uint32_t can be casted into a function pointer. And this needs not to be true: "[...] system-agnostic for all micro controllers [...]". Function pointers can have other widths than 32 bits. Pointers in general might consist of more than the pure address, for example include a selector for memory spaces, depending on the system's architecture.
If you got the address from a linker script, you might have declared it like this:
extern const uint32_t ext_func;
And like to use it so:
callFunctionAt(ext_func);
But you can change the declaration into:
extern void ext_func();
And call it directly or indirectly:
ext_func();
callFunctionAt(&ext_func);
The definition in the linker can stay as it is, because the linker knows nothing about types.
There is no generic way. It depends on which compiler you are using. In the following I'll assume avr-g++ because it's common and freely available.
Spoiler: On AVR, it's more complicated than on most other machines.
Suppose you actually have a uint32_t address which would be a byte address. Function pointers in avr-g++ are word addresses actually, where a word has 16 bits. Hence, you'll have to divide the byte address by 2 first to get a word address; then cast it to a function pointer and call it:
#include <stdint.h>
typedef void (*func_t)(void);
void callFunctionAt (uint32_t byte_address)
{
func_t func = (func_t) (byte_address >> 1);
func();
}
If you started with a word address, then you can call it without further ado:
void callFunctionAt (uint32_t address)
{
((func_t) word_address)();
}
This will only work for devices with up to 128KiB of flash memory!
The reason is that addresses in avr-g++ are 16 bits long, cf. the layout of void* as per avr-gcc ABI. This means using scalar addresses on devices with flash > 128KiB will not work in general, for example when you issue callFunctionAt (0x30000) on an ATmega2560.
On such devices, the 16-bit address in Z register used by EICALL instruction is extended by the value held in the EIND special function register, and you must not change EIND after entering main. The avr-g++ documentation is clear about that.
The crucial point here is how you are getting the address. First, in order to call and pass it around properly, use a function pointer:
typedef void (*func_t)(void);
void callFunctionAt (func_t address)
{
address();
}
void func (void);
void call_func()
{
func_t addr = func;
callFunctionAt (addr);
}
I am using void argument in the declaration because this is how you'd do it in C.
Or, if you don't like the typedef:
void callFunctionAt (void (*address)(void))
{
address();
}
void func (void);
void call_func ()
{
void (*addr)(void) = func;
callFunctionAt (addr);
}
If you want to call a function at a specific word address like, for example 0x0 to "reset"1 the µC, you could
void call_0x0()
{
callFunctionAt ((func_t) 0x0);
}
but whether this works depends on where your vector table is located, or more specifically, how EIND was initialized by the startup code. What will always work is using a symbol and define it with -Wl,--defsym,func=0 when linking with the following code:
extern "C" void func();
void call_func ()
{
void (*addr)(void) = func;
callFunctionAt (addr);
}
The big difference compared to using 0x0 directly it that the compiler will wrap symbol func with symbol modifier gs which it will not do when using 0x0 directly:
_Z9call_funcv:
ldi r24,lo8(gs(func))
ldi r25,hi8(gs(func))
jmp _Z14callFunctionAtPFvvE
This is needed if the address is out of the scope of EIJMP to advise the linker to generate a stub.
1 This will not reset the hardware. The best approach to force a reset is by letting the watchdog timer (WDT) issue a reset for you.
Methods
Yet another situation is when you want the address of a non-static method of a class because you also need a this pointer in that case:
class A
{
int a = 1;
public:
int method1 () { return a += 1; }
int method2 () { return a += 2; }
};
void callFunctionAt (A *b, int (A::*f)())
{
A a;
(a.*f)();
(b->*f)();
}
void call_method ()
{
A a;
callFunctionAt (&a, &A::method1);
callFunctionAt (&a, &A::method2);
}
The 2nd argument of callFunctionAt specifies which method (of a given prototype) you want, but you also need an object (or pointer to one) to apply it. avr-g++ will use gs when taking the method's address (provided the following call(s) cannot be inlined), thus it will also work for all AVR devices.
Based on comments I think you are asking about how microcontroller calls function.
Could you compile your program to see assembly files?
I would recommend you to read one of them.
Every function after compiling are translated to instructions that CPU can do (loading to register, adding to register etc.).
So then your void foo(int x) {statements;} compile to simple CPU instructions and whenever you call foo(x) in your program, you are moving to instructions that are related to foo - you are calling a subroutine.
As far as I remeber there is a CALL function in AVR to invoke subroutines and the name of subroutine is the label where executing program jump and invoking next instruction at adress.
I think you can clarify your doubts when you read some AVR assembly tutorials.
It is fun (at least for me) to see what exactly CPU do when it calls function that I wrote, but it required to know what instructions do. You develop in AVR so there is a set of instructions that you can read about in this PDF and compare with your assembly files.

Strange behavior of program on Qt 5

I'm writing two programs on Qt 5. The first ("Debug") program sends requests to the second ("Simulator") through a PCI-E device. The "Simulator" must respond as fast as possible. This is a separate issue, but now I want to ask about another strange effect. The "Debug" program writes 10 bytes from QLineEdit to a PCI-E device and then waits for an answer from the "Simulator". When the answer came fast enough, I see the right data bytes in the "Debug" program window, otherwise a PCI-E device returns a copy of a sended data and I see it too. The issue is that data can be sended by two ways: by clicking the Send button on the form and by clicking the Return button on a keyboard. In both cases the data is sent from the following slot:
void MyWin::on_pushButton_Send_clicked()
{
if(data_matched)
{
QString exp = ui.lineEdit_Data->text();
QStringList list = exp.split(QRegExp("\\s"),
QString::SkipEmptyParts);
for(int i=0; i<list.size(); i++)
{
quint8 a = list[i].toUInt(0, 16);
data[i] = a;
}
write_insys(bHandle, data, DataSize);
ui.textEdit->append( /* show sended bytes */ );
read_insys(bHandle, data, DataSize);
ui.textEdit->append( /* show received bytes */ );
}
}
But in the second case (on Return key press) the only difference is that the above slot is invoked inside the following:
void MyWin::on_lineEdit_Data_returnPressed()
{
on_pushButton_Send_clicked();
}
But the results:
1st case: 90% wrong answers
2st case: 90% right answers
The code of write_insys and read_insys is absolutely trivial, simply call the library functions:
bool write_insys(BRD_Handle handle, void* data, int size)
{
S32 res = BRD_putMsg(handle, NODE0, data, (U32*)&size, BRDtim_FOREVER);
return (res >= 0);
}
bool read_insys(BRD_Handle handle, void* data, int size)
{
S32 res = BRD_getMsg(handle, NODE0, data, (U32*)&size, BRDtim_FOREVER);
return (res >= 0);
}
Does anyone know why this might happen?
Windows 7, Qt 5.4.2, Msvc 2010.
edit: Most likely it is a Qt bug...

protothread jump a thread to the beginning in the external main function

I have a protothread set up and blocking ...
static int mythread(struct pt *pt){
static int k;
PT_BEGIN(pt)
while(1){
PT_WAIT_UNTIL(pt, eventA == 1); // blocked at lineA
for(k=0;k<100;k++){
//do something
PT_YIELD(pt); //blocked at lineB
}
PT_WAIT_UNTIL(pt, eventB == 1); //block at lineC
}
PT_END(pt)
}
After a while, mythread can be blocked at "lineA", "lineB", or "lineC".
How could an external function, like main() reset mythread to be blocked at the beginning "lineA" again.
By running the macro PT_RESTART(&pt_mythread)? The compiler doesn't like it. Because my main() function isn't inside PT_BEGIN, PT_END block, so the return inside that macro is bad, bad.
Or running PT_INIT(&pt_mythread) again? Any suggestions?
Yes, calling PT_INIT from outside the protothread will restart it. If you look at the source for PT_RESTART:
#define PT_RESTART(pt) \
do { \
PT_INIT(pt); \
return PT_WAITING; \
} while(0)
This is exactly what it does, but then also returns (like a yield) out of the thread. As you say it's designed to be called from inside the protothread.
The protothread struct is basically just a number representing where it was in the thread:
struct pt {
lc_t lc; // where lc_t is an unsigned short;
};
So the only thing we need to do is reset that number to zero, which is exactly what PT_INIT does.

Move semantics in Qt without pointers?

I have a Qt project, there I have an Object, which is going to be copied a lot of time. Therefor I would like to add move semantics.
#ifndef OBJECTTOCOPY_H
#define OBJECTTOCOPY_H
#include <QColor>
#include <QString>
#include <QDataStream>
namespace level_1 {
namespace level_2 {
class ObjectToCopy {
public:
explicit ObjectToCopy(const QString& _name = "", const QColor& colorBody = QColor() );
// MOVE
ObjectToCopy(ObjectToCopy && other);
static quint32 _valueInt32;
static quint16 _valueInt16;
QString _name;
QColor _colorBody;
private:
};
}
}
#endif // OBJECTTOCOPY_H
How do I steal the pointers of the member variables, since they are no pointers?
ObjectToCopy::ObjectToCopy (ObjectToCopy&& other)
: _valueInt32( other._valueInt32 )
, _valueInt16( other._valueInt16 )
, _name( other._name )
, _colorBody( other._colorBody )
{
other._valueInt32 = 0;
other._valueInt16 = 0;
other.name.clear();
other._colorBody = QColor();
}
Does that make sense for non-pointers?
Is it ok to reset QString 's like string.clear(); to mark that for the garbage collector?
How could I reset a QColor object?
You can add move semantics of course, but in your case there is no need in this at all. quint32, quint16 are moved by copying. QColor is wrapper around union and has no move constructor (and doesn't need one) and will also be moved by copying. QString is reference counted type in QT. It has move constructor in recent versions of library, but the difference in speed will be minimal (difference between swapping pointer and incrementing reference counter).
You are looking for std::move:
ObjectToCopy::ObjectToCopy (ObjectToCopy&& other)
: _valueInt32( other._valueInt32 )
, _valueInt16( other._valueInt16 )
, _name( std::move(other._name) )
, _colorBody( std::move(other._colorBody) )
{
other._valueInt32 = 0; //probably not necessary
other._valueInt16 = 0; //probably not necessary
//other.name.clear(); //not necessary
//other._colorBody = nullptr; //not necessary
}
It makes sense to move non-pointers. You are in the process of making such an object. Moving integers doesn't help, but doesn't hurt either, so you may as well do it for consistancy. Moving things that don't have a move constructor also works: If no move constructor is available the copy constructor is used (moving is not always better, but not worse either).
The implementation above says "move by copying the ints and moving the name and the _colorBody".
Make sure you do not read from variables you moved from.
It is ok, but not necessary. other is supposed to be a temporary that will get destroyed anyways. (C++ does not have a garbage collector in your sense)
Also once an object is moved from it tends to be in the cleared state like for QString, but that is not always the case.
You cannot really. You can assign a default constructed one like other._colorBody = QColor(); but that just means it sets the color to black. A QColor cannot be empty, it always has some color.
Also read What are move semantics?

How to open a file in Qt-method but read it use C-language function?

I know Qt has a lot of good methods for reading file.But in my work , I have to open a file by using Qt and get a pointer pointing to the start address of the file.So how to do that?
Here is my codes:
char *buffer;
if(file.open(QIODevice::ReadOnly))
{
QByteArray dataArray=file.readAll();
buffer=dataArray.data();
}
char test[1024];
for(int i=0;i<1024;i++)
{
test[i]=*buffer;
buffer++;
}
I use QByteArray QIODevice::​readAll()to read all available data from the device, and returns it as a byte array.
Then I use char * QByteArray::​data() to set my pointer buffer.
But when I try to read the data by a for loop,my Qt debugger throw me an error:read access violation,so how would this happen?
BTW , the file to be read is very big so I can't use a buffer to read them all once. Instead , I have to do as what I did here. When I read a 7kb-sizes-file ,my codes runs well. When I read a 700kb-sizes-file , here comes the problem.
The reason you are getting access violation is that dataArray is declared inside if code block and goes out of scope. You want to declare the dataArray outside of that block, eg:
QByteArray dataArray;
if(file.open(QIODevice::ReadOnly))
{
dataArray = file.readAll();
}
else
{
// give error
}
char *buffer = dataArray.data();
char test[1024];
for(int i = 0; i < 1024; i++)
{
test[i] = *buffer;
buffer++;
}
There are other potential problems in your code though:
First, what if the size of data read from the file is less than 1024? Then you will be reading past the end of the buffer (more access violations).
Second, what if the file is really big? Reading all that data at once may cause swapping/paging.

Resources