Solved qDebug output the message from point to QString::toLocal8Bit().data();
-
@jonb thanks for your reply, the first is quite right, but the last three is wrong, i cannot understand it.
-
Hi,
void *ptr1 = (void*)str.toLocal8Bit().data();
this line and the other similar are likely giving you a warning.From a lifetime point of view the QByteArray returned by
toLocal8Bit
ends at the the semicolon. The fact that the memory address you get is the same for all these calls is just luck and as you have seen, the content of that memory segment may have changed because the object that used to use it has already been destroyed and thus it may have been reused for something else.If you want to play with the data contained in that QByteArray you have to do it like this:
QByteArray local8BitRepresentation = str.toLocal8Bit(); void *ptr1 = (void*)local8BitRepresentation.data(); void *ptr2 = (void*)local8BitRepresentation.data(); // etc.
-
@welsey
I had already appended to my reply about this. Read that. I believe we must be talking about temporary areas here, think about where thesetoLocal8Bit()
results are getting stored/released?I see @SGaist is confirming this, and suggesting you need to put it into a named
QByteArray
so that you can play with it without it getting disposed in the middle of what you're doing. -
@sgaist
I'd like to press you on this, as it's quite interesting (to me at least!). Remember I am not a Qt C++-er, so I cannot test for myself.Looking at the code. What is it that can actually change after line 1 and before line 2:
qDebug()<<ptr1<<*(unsigned char*)ptr1; qDebug()<<ptr2<<*(unsigned char*)ptr2;
? Qt does not do resource releasing in a separate thread. So I see only two possibilities as to how the second line can see different content from the first one:
-
There is an actual instruction in the machine code after line 1 which causes release. But I don't see that there will be?
-
It is the fact that the user called a Qt function like
qDebug()
, which itself uses Qt stuff which causes the context to be released/changed? It must be this?? So if OP had instead written:
unsigned char c1 = *(unsigned char*)ptr1; unsigned char c2 = *(unsigned char*)ptr2; qDebug()<<ptr1<<c1; qDebug()<<ptr2<<c2;
then the results would be the same?
-
-
@sgaist yeah, it's right, i think this is the answer, thanks a lot.
-
@jonb Between these two lines you can have lots of stuff happening. Don't forget that there's a lot of things going on your machine while you execute your program.
As for memory releasing, it's nothing Qt specific. The object is destroyed but you can have the next one re-created in the same place or a different one.
-
@JonB i tested it and it worked;
-
@jonb Between these two lines you can have lots of stuff happening. Don't forget that there's a lot of things going on your machine while you execute your program.
Sorry, I don't get this at all. (It may be that this is a discussion for another topic...) So far as I am aware, there is nothing which can/will change the memory area inside a process from "other things going on on machine" in the middle of normal instructions inside one's code. Unless there is another thread operating here (which I don't think there is), nothing will happen to its memory space which cannot be seen from direct instructions inside the code where we are, and I don't see anything which could do that. The fact that I believe the OP is posting it does not get altered if he tries my alternative code which does not call
qDebug()
between the two lines proves that the cause is whatever is happening insideqDebug()
(within the process) which gives rise to the behaviour witnessed. -
The main problem with the code
void *ptr1 = (void*)str.toLocal8Bit().data();
is, thatptr1
is not valid.Why is this?
str.toLocal8Bit()
creates a (temporary)QByteArray
, which we could assign to a variable:QByteArray b = str.toLocal8Bit();
That would be a completely valid operation. Afterwards, we could even get a valid pointer to this array:QByteArray b = str.toLocal8Bit(); void *ptr1 = (void*)b.data();
Here
ptr1
would be valid as long as b is valid (until the scope is closed).So, why is
void *ptr1 = (void*)str.toLocal8Bit().data();
wrong?Because the temporary
QByteArray
is created and destroyed in the same line, hence theptr1
points to invalid memory. Accessing this memory is undefined behavior. The object may still be there (and everything works) or not (and everything crashes).Edit: Side note for completeness: You can use something like
const QByteArray &b = str.toLocal8Bit();
(holding a reference to the temporary object). In this case, the compiler knows what you are doing and extends the lifetime of the temporaryQByteArray
untilb
goes out of scope.But this only works for references!
Regards
-
@aha_1980
In the politest way. I do understand all of this. It is the answer to why the OP should not be writing the code he did. It is not the answer to what I am interested in, which is how the value at a given memory location gets changed between two consecutive statements which read it. My question is what changes it between these two lines (simply because I am interested).It seems to me that what the OP reports proves (to me) that it is the
qDebug()
on the first line which, as a (quite understandable) side-effect, is writing to the memory location. I did not spot that at first. I do not see what else it can be. -
@jonb said in qDebug output the message from point to QString::toLocal8Bit().data();:
It is not the answer to what I am interested in, which is how the value at a given memory location gets changed between two consecutive statements which read it. My question is what changes it between these two lines (simply because I am interested).
And that's what I liked to point out: we are talking about accessing invalid memory. You simply cannot do that.