PDA

View Full Version : Odd QString/QChar Addr Issues



Syndacate
4th March 2017, 11:43
So I'm working with a QTextEdit and came across some weird address issues...The code is below but the long and short of it is I'm seeing different addresses when I call constData() on the QString. I'm OK with this, sure, maybe QT changes the state the QString when you call constData(), but what I can't wrap my head around is that when first called in the for loop the addresses are equal, yet later they are not. Each iteration the same thing happens - they're back to being equal at the beginning of the loop. Consistently off by 0x800. The "c" pointer is invalid and dereferencing it returns 0. The full call yields the correct QChar info.

Anybody have any idea what is going on? I feel like I'm caught in some weird "gotcha" but I have no idea what. I'm not even entirely sure what the difference is between top/bottom.
The first addresses make sense since a QChar is 16bits, and the saved pointer is working as it should (it matches). Though for whatever reason that one call does not cooperate...



const QChar *c = results_box->toPlainText().constData();
for (int i = 0 ; i < results_box->toPlainText().size() ; ++i)
{
std::cout << " c=" << &(c[i]) << std::endl;
std::cout << "full=" << &(results_box->toPlainText().constData()[i]) << std::endl;
if (0)
{
std::cout << "Addr different" << std::endl;
}
else
{
std::cout << "Full call: " << &(results_box->toPlainText().constData()[i]) << " : " << (results_box->toPlainText().constData()[i]).toLatin1() << std::endl;
std::cout << "Saved call:" << &(c[i]) << " : " << c[i].toLatin1() << std::endl;
}
}


Output:


c=0000000000455818
full=0000000000455818
Full call: 00000000004560A8 : .
Saved call:0000000000455818 :
c=000000000045581A
full=000000000045581A
Full call: 00000000004560AA : .
Saved call:000000000045581A :
c=000000000045581C
full=000000000045581C
Full call: 00000000004560AC : \
Saved call:000000000045581C :


TIA!

anda_skoa
4th March 2017, 13:12
Not sure what you are asking for.

Are you wondering why different objects have different addresses?

Cheers,
_

d_stranz
4th March 2017, 19:01
Anybody have any idea what is going on?

Every time you call "results_box->toPlainText()" you are asking QTextEdit to return to you a temporary QString that contains the text edit content converted to plain text. As anda_skoa said, you're getting a different object every time, so it shouldn't be a surprise that they have different addresses.

Syndacate
6th March 2017, 18:47
OK, sorry for long reply, didn't get subscript notif. Sorry you guys didn't understand, let me try to explain better:

Let's take a look at the outside (not in 'if' statement) calls:

c=0000000000455818
full=0000000000455818
c=000000000045581A
full=000000000045581A
c=000000000045581C
full=000000000045581C

So No, every time "toPlainText()" is called it's not returning a new object. It's returning the same memory (base at 0x455818). The addresses under "full" are 16 bit sequential and toPlainText() is called each time.. (818, 81A, 81C). This is fine. Rather expected behavior. I know you're not guaranteed that the object is the same each time - but it is here for each iteration.

I'm concerned about the difference in behavior outside and inside.

Obviously 'c' is pointing to same address as "results_box->toPlainText()" each call (which implies it's the same object returned each time), but inside (and only inside) the 'if' statement when I call: "results_box->toPlainText().constData()" it returns a new address (ok, fine, let's say that's expected because it returned a new object) but then AFTER (the next iteration) outside the 'if' they point to the same addr again. This behavior of matching and not matching is very confusing to me.

So basically what happens is as follows:


Iteration 0:
Outside 'if': 'c' and full call point to same address (ie. 0x80) (EXPECTED
Inside 'if': 'c' points to 0x80, full call points to 0x880 (MAYBE EXPECTED (if each call yields new object))
Iteration 1:
Outside 'if': 'c' and full call point to same address again (0x82) (NOT expected if we take assumption that full call returns new object)
Inside 'if': 'c' points to 0x82 (EXPECTED) but full call points to arbitrary address ('c' no longer valid)
Iteration 2:
Outside 'if': 'c' and full call point to same address (NOT expected, especially since 'c' was just invalid at end of iteration 1)
...

So basically I'm concerned with the difference in behavior between inside and outside the 'if'. You guys are saying that it's returning a new object each time. If that's the case then it's strange that outside the 'if' statement it literally returns the same exact base address for each of the many iterations. OUTSIDE the 'if' the print doesn't reflect what you're saying, but INSIDE the 'if' statement it does. I don't get how that's possible.

Synopsis:
You're likely saying "why do you care?" My code (how I stumbled on this issue) was originally as follows:


const QChar *c = results_box->toPlainText().constData();
for (int i = 0 ; i < results_box->toPlainText().size() ; ++i)
{

if (0)
{
//never goes in here, I forgot what it was originally..
}
else
{
std::cout << "Saved call:" << &(c[i]) << " : " << c[i].toLatin1() << std::endl; //!!!! c[i] returns ASCII 0 for all values, completely unexpected to me - I just wanted a pointer to the char data inside the field.
}
}


I was originally thinking as you guys are saying that each call will return a new QString object each time and the QString is no longer valid but when I printed the addresses outside the 'if' statement in the for loop it all shows the same object at the original base

Hope that elaborates what I originally tried (and what went wrong) and how I got lead into this interesting scenario.

anda_skoa
7th March 2017, 09:40
I was originally thinking as you guys are saying that each call will return a new QString object each time and the QString is no longer valid

Exactly.
That's what it does.



but when I printed the addresses outside the 'if' statement in the for loop it all shows the same object at the original base

Since the data gets temporarily allocated and the deallocated, the next allocation can sometimes happen at the same memory location.

Why do you even want to convert the text edit's content into plain text multiple times?
The resulting string content won't change if the internal content doesn't change.

Cheers,
_