Definition of qPrintable:
# define qPrintable(string) QString(string).toLocal8Bit().constData()
toLocal8Bit returns a QByteArray. Documentation of QByteArray::constData():
The pointer remains valid as long as the byte array isn't reallocated or destroyed.
toLocal8Bit() creates a temporary QByteArray, which is destroyed just after constData() has been called. So the pointer returned by constData points to freed memory.
Am I missing something here?
Additional comments:
Documentation of qPrintable states this:
The char pointer will be invalid after the statement in which qPrintable() is used. This is because the array returned by QString::toLocal8Bit() will fall out of scope.
But what does this mean? For my understanding, this is identical to "The pointer is invalid from the moment it is returned by qPrintable"
Why I am asking:
I have seen code failing which can be simplified like this:
someFunction( stringA.toLatin1().constData(), stringB.toLatin1().constData())
Inside the called function, both parameters were pointers to the same address.
qPrintable macro is supposed to be used for debugging purposes:
qWarning("%s: %s", qPrintable(key), qPrintable(value));
or:
qDebug() << "My value is: " << qPrintable(value);
Here temporary QByteArray object created by QString::toLocal8Bit is destroyed after the whole statement finishes, which happens after QByteArray::constData() pointer is utilized.
And in this case we have a problem you have described:
QString s = "Hello";
const char *debug_string = s.toLocal8Bit().constData();
// Can't use debug_string here as the pointer is invalid:
// qDebug() << debug_string
For my understanding, this is identical to "The pointer is invalid from the moment it is returned by qPrintable"
No. Temporary objects are destroyed at the end of the full expression they're part of, unless their life is prolonged by taking a const reference. See this question for details. The pointer is invalid as soon as the full expression ends.
In a call like foo(obj1().method(), obj2().method()), the entire call is a full expression.
So, this will work:
#include <QtCore>
struct Test {
Test() { qDebug() << "created"; }
~Test() { qDebug() << "destroyed"; }
Test * fun() { return this; }
};
void f1(Test *, Test*) { qDebug() << "f1"; }
int main()
{
f1(Test().fun(), Test().fun());
}
Output:
created
created
f1
destroyed
destroyed
I have seen code failing which can be simplified like this: someFunction( stringA.toLatin1().constData(), stringB.toLatin1().constData()). Inside the called function, both parameters were pointers to the same address.
The "simplifications" do matter. As soon as you pull each qPrintable out of the full function call expression where they are used as arguments, things fail:
int main()
{
auto a1 = Test().fun();
// here a1 dangles
auto a2 = Test().fun();
// here both a1 and a2 dangle
f1(a1, a2); // undefined behavior
}
Output:
created
destroyed
created
destroyed
f1
Is qPrintable prone to access violations?
That depends on how aware one is of the semantics of C++. Given that it's an obsolete and unnecessary construct, I'd simply say: prone to undefined behavior or not, there's no reason to use it. If you need to pass a QString to something expecting const char *, be explicit about it in an adapter.
void foo(const char *); // we need to call this with a QString
void foo2(const char *, const char *);
inline void foo(const QString & arg1) { // now we can
auto a1 { arg1.toLocal8Bit() };
foo(a1.constData()); // a1's lifetime explicitly extends past the call
}
// or if you really like one-liners
inline void foo2(const QString & arg1, const QString & arg2) {
foo2(arg1.toLocal8Bit().constData(), arg2.toLocal8Bit().constData());
}
But what does this mean? For my understanding, this is identical to "The pointer is invalid from the moment it is returned by qPrintable"
I had the same question, but the key to understanding this is noticing that qPrintable is a macro, not a function:
#ifndef qPrintable
# define qPrintable(string) QtPrivate::asString(string).toLocal8Bit().constData()
#endif
(from here).
If it were a function, you'd be right. Being a macro, there is no return to speak of. The documentation says "returns", but that is just imprecise. Thus, the scope of the temporary is the scope where qPrintable is invoked.
Related
maybe this question will be a bit complicated and maybe i'm missing something of stupid.
I'll try to explain without any source code, because my project is big and i don't know how/where to start.
I have:
bool result = false;
bool* pointer = &result;
these variables are stored in some classes.. (not as in the above code).
When result is created, his address is something like 0x28fddc.
and the pointer variable takes this address.
Suddendly, without any reason (maybe), his address is not 0x28fddc anymore but something like 0x3a8c6e4.
With the pointer variable, i am trying to change the result var by doing:
*result = true;
But obviously, this doesn't work (and it doesn't give me any error). It will not change result var because it's in another address.
I don't know why this happens.
Can you only tell me how could this happen? And i'll try to fix.
(This classes are everytime being updated in some functions with parameters passed by reference).
For example:
void update_class(obj_class &obj);
(These names are only an example).
I hope i've been clear and if not, i'll just delete this topic.
Sorry for bad english but i'm italian :)
EDIT:
Now i'll try to provide some code..
button.h
class button
{
public:
void check_tap(SDL_Event* e);
bool* done;
}
messagebox.h:
class messagebox
{
public:
messagebox();
bool result_ok;
button btn_ok;
}
void check_tap(std::vector<messagebox> &msgbox, SDL_Event* e) {
for(unsigned int k=0; k<msgbox.size(); k++) {
msgbox[k].btn_ok.check_tap(e);
// check_tap is a function that i create for checking if the user is tapping the button with his finger or not. When the user presses the button and leaves it the done variable should become true, but result_ok seems not to be affected because his address here is different. This problem is only in this case using messagebox. I created more other buttons outside and all works perfect.
}
}
messagebox.cpp:
messagebox::messagebox() {
// Initializing things
btn_ok.done = &result_ok;
// Here, btn_ok.done gets the address of result_ok..
}
main.cpp:
std::vector<messagebox> msgbox;
msgbox.push_back(msgbox());
No, the address of variables do not change during their lifetime.
However, storing the address of a variable is problematical if the variable ceases to exist. A simple example is
#include <iostream>
int *p;
void f()
{
int i;
p = &i;
}
int main();
{
f();
std::cout << (void *)p << '\n';
// other code here
f();
std::cout << (void *)p << '\n';
}
In the above case, the two values of p may be the same, or they may differ. This is not because the address of variables change. It is because a variable, i is created each time f() is called, and ceases to exist when f() returns. The variable i in the first call of f() is, as far as your program is concerned, a distinct variable from i during the second call of f().
Depending on what happens with "other code here" in the above, the memory occupied by i in the first call of f() may be inaccessible (e.g. used for another variable) during the second call of f() - so, during the second call of f(), i will have a different address than during the first. There are no guarantees - you may also get lucky (or unlucky depending on how you look at it) and the addresses printed will be the same.
If you are getting behaviour that suggests, to you, that the address of a variable is changing then - somewhere in your code - there is a bug of some form. Typically, this will involve storing the address of a variable in a pointer, and using (or accessing the value of) the pointer after the variable ceases to exist. And any dereferrencing of that pointer (e.g. to access the variable pointed at) has undefined behaviour.
For example, any usage of *p like
*p = 42;
or
std::cout << *p << '\n';
in the main() I have given above will give undefined behaviour.
The act of assigning a pointer to contain the address of that variable does not change the lifetime of that variable.
Everytime I encounter the situation dealing with c string, I'm very confused.
why are those two prints have same result?
In my understaning, first function assigns the address of string at text variable. which seems proper to me. But the second function assigns the address at where text variable points to. what happened here?
#include <iostream>
#include <cstring>
void getText(char** text) {
*text = strdup("AAAAA");
}
void getText2(char* text) {
text = strdup("AAAAA");
}
int main()
{
char* text;
getText(&text);
std::cout << text << std::endl; // prints "AAAAA"
getText2(text);
std::cout << text << std::endl; // prints "AAAAA"
}
This function
void getText2(char* text) {
text = strdup("AAAAA");
}
has a memory leak.
Function parameters are function local variables.
You can imagine the definition of the function getText2 and its call the following way. I renamed the function parameter that it would be more clear.
getText2(text);
//...
void getText2( /*char* parm_text */) {
char *parm_text = text;
parm_text = strdup("AAAAA");
}
The local variable that is the parameter parm_text will be destroyed after exiting the function. However the allocated memory in this statement
parm_text = strdup("AAAAA");
is not freed.
On the other hand the argument itself was not changed. The function used the value stored in the argument that was assigned to the local variable.
You could declare the parameter as reference to the argument. For example
void getText2(char* &text) {
^^^^^
text = strdup("AAAAA");
}
In this case it is the argument itself that is changed in the function.
As for the function
void getText(char** text) {
*text = strdup("AAAAA");
}
then the argument is passed indirectly by using a pointer to the argument. So inside the function the value of the argument is changed.
In the first case, you passed a pointer to your local pointer, you dereference that pointer and make it point to the value returned by strdup(), you are modifying the address the original pointer points to.
In the second one, you pass the poiner itself, you cannot alter it inside the function because even if the two pointers point to the same memory initially, they are stored in different places, so altering the address of one doesn't affect the other.
If you alter the data the pointer points to, and not the address in getText2() then it will change, like
text[0] = 'B';
text[1] = 'B';
text[2] = 'B';
text[3] = 'B';
text[4] = 'B';
You should also call free() after you use the pointer returned by strdup() or it will be a memory leak.
Finally, using pointers in c++ is currently considered bad practice unless you are a library programmer, which I don't think is the case. Instead, use std::string and all the c++ concepts (like pass by reference which doesn't exist in c) that will allow you to write modern c++ programs.
Passing by reference in c++ is possible
void getText(std::string &text)
{
text = "AAAAAA";
}
void getText2(std::string &text)
{
text = "BBBBBB";
}
int main()
{
std::string text;
getText(text);
std::cout << text << std::endl;
getText2(text);
std::cout << text << std::endl;
return 0;
}
There you go, no memory leaks, it works as expected, and it's modern c++.
Supposing I have two functions, one like:
const char* getstr()
{
std::string s = "somestring";
return s.c_str();
}
second like:
void func(int x, const char* str)
{
std::cout <<"x="<<x <<", str=" <<str<<std::endl;
}
And now suppose 'func()' with something like
func(100,getstr());
My question is when will the function stack for function "getstr()" be unwinded ?
After the body of "func()" is executed or before the body execution happens ?
I am asking this because some genius in my team wrote this type of "getstr()" function. and somehow the system is not crashing.
My understanding was that the stack for function "getstr()" will be unwinded as soon as that parameter is evaluated. But if that was true the code would have crashed and it is not happening.
Can someone help me what c++ standard says ?
s gets destroyed before getstr returns. The pointer that getstr returns is dangling.
I am trying to pass in a empty struct pointer into a function called "initialize" as an output parameter and then after the function finishes I could retrieve the object pointed by the struct pointer. Some unexpected behaviors occur and I don't quite understand.
Below is my code:
static void initialize(complex_struct*& infoPtr)
{
complex_struct myInfo;
infoPtr = &myInfo;
// some other codes that modify the contents of myInfo
infoPtr->input_components = 3;
}
static void myfunction()
{
complex_struct* infoPtr = nullptr;
initialize(infoPtr);
std::cout << infoPtr->input_components << std::endl;
}
The output of this is an arbitrary large integer number. But I was expecting an integer 3 is printed.
Restrictions:
I cannot modify complex_struct; it is a third_party struct that needs to be used.
Also, the reason why I need initialize() to be a separate function is that I am doing performance measurement on the memory allocation of complex_struct. So moving the first line of code in initialize() to myfunction() is not an ideal solution.
You are trying to use the pointer to local variable outside of it's scope funciton. In your example, myInfo instance inside initialize() will be deleted after you exit the function, and the address you remembered will be pointing to random garbage memory. You should never use pointers to local variables outside of their scopes.
How to fix the issue? The easiest way would be to ditch the pointer here, and instead pass your struct by non-const reference. Code would look like following:
void initialize(complex_struct& info)
{
// some other codes that modify the contents of myInfo
info.input_components = 3;
}
void myfunction()
{
complex_struct info;
initialize(info);
std::cout << info.input_components << std::endl;
}
There is one subtle flaw in the suggested code: effectively info is initialized twice. First time when it's instance is created (complex_struct info) and the second time inside initialize() function. It would not have any noticeable effect in this example (info is allocated on the stack, and I do not think it has any non-trivial constructor) but might be of bigger problem in other setting. The best way to initialize it in this case would be to return the struct from the initialzer function, and rely on copy-elision to optimize away all the copies. Illustration code:
complex_struct initialize()
{
complex_struct info;
// some other codes that modify the contents of myInfo
info.input_components = 3;
return info;
}
void myfunction()
{
complex_struct info = initialize();
std::cout << info.input_components << std::endl;
}
You are returning a pointer to an object in the stack frame. That object gets deleted when the function returns. You have a dangling pointer in myfunction.
Ways to solve the problem:
Allocate memory from heap
static void initialize(complex_struct*& infoPtr)
{
infoPtr = new complex_struct ;
infoPtr->input_components = 3;
}
Make sure to deallocate the memory in the calling function.
Use an object, instead of a pointer
static void initialize(complex_struct& info)
{
info.input_components = 3;
}
and change its usage:
static void myfunction()
{
complex_struct info;
initialize(info);
std::cout << info.input_components << std::endl;
}
Why is it that I can access the data held within the object after assigning the pointer WHILE I'm within the scope of the assigning function, but cannot once I try to access the same value through the same pointer but outside of that function?
The pointer is a member function and is assigned within the function. Within the function, that works fine. But, when from within that function, I call ANOTHER function which uses the class scope, the pointer misbehaves, presenting garbage data. Why?
CODE:
#include <iostream>
class Object{
public:
Object( ) { std::cout << "Object constructor called." << std::endl; }
Object( const Object &in ) { i = in.i; std::cout << "Object copy constructor called." << std::endl; }
~Object( ) { std::cout << "Object destructor called." << std::endl; }
int i;
};
class ObjectManager{
public:
Object * retObject(){
Object *myObject = new Object;
myObject->i=55;
return myObject;
}
};
class LogicManager{
public:
LogicManager(){
myObjectManager = new ObjectManager;
}
~LogicManager(){
delete myObjectManager;
}
Object * retObject(){
return myObjectManager->retObject();
}
private:
ObjectManager *myObjectManager;
};
class Viewer{
public:
~Viewer( ) { if( myObject ) { delete myObject; } }
void ptrinObject( LogicManager * inLogic ){
myObject = inLogic->retObject();
std::cout << "Got path size of " << myObject->i << std::endl; //correct
std::cout << "Got path size of " << retObjectVal( ) << std::endl; //0?!?!?!?
}
int retObjectVal( ) { myObject->i; }
private:
Object *myObject;
};
int main(){
LogicManager myManager;
Viewer myViewer;
//myViewer.cpyinObject( &myManager );
myViewer.ptrinObject( &myManager );
return 0;
}
OUTPUT:
Object constructor called.
Got path size of 55
Got path size of 861280848
Object destructor called.
The problem is:
int retObjectVal( ) { myObject->i; }
There is no return statement in that function. You just have an expression with no side effect. As a result, we run into ยง6.6.3/2:
Flowing off the end of a function is equivalent to a return with no value; this results in undefined
behavior in a value-returning function.
It's undefined behavior what it returns, so it ends up returning some garbage. Just make it:
int retObjectVal() { return myObject->i; }
This is an easy mistake to make, which is why you should always try to compile with the highest warning settings possible. For instance, on gcc with no flags, I get no warnings. But with -Wall, I get:
warning: statement has no effect [-Wunused-value]
warning: no return statement in function returning non-void [-Wreturn-type]
First, you're not initializing Viewer::myObject so if you just do
void something() {
Viewer v;
}
You may end up trying to delete an invalid pointer.
myViewer.cpyinObject( &myManager );
myViewer.ptrinObject( &myManager );
Both functions create a new Object but neither checks to see if there's already one allocated (memory leak). Then later, they immediately ignore that new object created and instead assign yet another new Object allocated by ObjectManager (more memory leaks).
Finally, Viewer::retObjectVal does not actually specifically return a value and therefore you are receiving "junk off the end of the function".
I suggest you look at your compiler warnings as any sensible compiler will have warned you about the first and third issues I've mentioned.
In the Viewer class, you are missing a return statement:
int retObjectVal( ) { return myObject->i; }
should work.
What you have is a method where some of its branches fall off without returning a value. This leads to undefined behavior. You are simply evaluating "myObject->i;" as a statement.
Another issue you should probably address is that your Object pointers are not owned by anyone and not being deleted anywhere. Namely, you are deleting your ObjectManager but nowhere does it delete the underlying object itself. You should probably figure out an ownership model there, have someone keep track of these pointers, and delete them when appropriate.