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.
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.
Based on the idea of this entry Is it a good idea to return “ const char * ” from a function?
I thought to extend this with another question I have.
Consider the following code:
#include <string>
#include <cstdio>
const char * GetSomeString()
{
std::string somestlstring;
somestlstring = "Hello World!";
return somestlstring.c_str();
}
int main()
{
const char * tmp = GetSomeString();
printf("%s\n", tmp);
return 0;
}
If I build it with
g++ source.cpp -o executable
and execute that, I get strange symbols displayed. This is because somestlstring is destroyed through the callstack and the pointer you keep after returning became invalid.
My question is: how should I design a method or function that does not have such behaviour without actually declaring additional global variables or potential member functions?
You should drop the whole C mindset and start writing C++:
#include <string>
#include <iostream>
std::string GetSomeString()
{
std::string somestlstring;
somestlstring = "Hello World!";
return somestlstring;
}
int main()
{
std::string tmp = GetSomeString();
std::cout << tmp << std::endl;
return 0;
}
One obvious solution is to make the return type std::string.
how should I design a method or function that does not have such beahviour without actually declaring additional global variables or potential member functions?
Not at all. If you return a const char *, your function is kind of telling the caller "here you have a C string to use, but it stays mine" *), and this implies the caller doesn't have to bother releasing the resources, for example. So you can do this from an instance method (returning a pointer to a field) or you can have a function return a pointer to some static buffer (global variable).
If you want to return a dynamically allocated C string from a function, you must return char * instead and the caller has to free() it when done using it.
That all said, in C++ this doesn't make much sense, except when somehow interfacing with C code. If you want to write C++ code, go with nvoigt's answer.
*) this is thinking in terms of ownership, which is very helpful dealing with manually managed resources. The owner of something is responsible for appropriate cleanup. You can only return a const raw pointer if you don't transfer ownership of the object to the caller.
You are currently referencing the memory of a local std::string object which is destroyed when the object goes out of scope (when returning from the function)
if you really want to return a const char *:
you have to make your std::string static (but only 1 value is shared by your application)
or you have to duplicate the string memory (but you need to free it or you get memory leaks, like happened a lot with the old str() method of the old strstream object, which was later converted to std::string)
But as others said, better stick to C++ std::string (or const reference) as a return value and take c_str() of that returned string when needed for C-style interfaces.
std::string tmp = GetSomeString();
FILE *f = fopen(tmp.c_str(),"r");
The local string variable in the GetSomeString() function will get out of scope after you returned from the funtion. You will be printing random stuff that is in the memory position where the string was before. Try this:
#include <string>
#include <cstdio>
void GetSomeString(std::string& str)
{
str = "Hello World!";
}
int main()
{
std::string str;
GetSomeString(str);
std::cout << str << std::endl;
return 0;
}
Simply put: I want to write to a file whenever my program exits, so I have an object that accepts a filename (char*) and a reference to a Google Protobuf Message (for these purposes, you can just pretend that it's a string&) in the constructor and then writes the message to the filename in the destructor. Then, in main(), I initialise one of these objects and declare it as static (so it will destruct when the program exits for any reason).
My code had been working perfectly for several revisions before I changed something (seemingly) unrelated, and now it doesn't work. Now, when the object destructs, the char* and reference both point to unintialised versions of char and Message. I have the related code below:
using namespace std;
class WriteOnShutdown {
private:
const char* filename;
public:
MathHelper::Log& message;
WriteOnShutdown(char* a, MathHelper::Log& b) : filename(a), message(b) {}
~WriteOnShutdown() {
cout << "debug\n";
//*filename is -52 (unitialised char)
//READ ACCESS VIOLATION - message is still valid, but message.DebugString tries to call a pointer which hasn't been initialised yet
cout << message.DebugString() << endl;
}
};
int main() {
char filename[100];
MathHelper::Log log;
//Initialise filename and log
static WriteOnShutdown write(filename, log);
//Do program stuff here
//Then, at the end of main(), printing write.message.DebugString() works like a charm
cout << endl << write.message.DebugString();
_getch();
}
The reason why you have a problem is following:
MathHelper::Log log is going to be destructed before your main returns, but destructor of WriteOnShutdown will be called after main returns.
Since WriteOnShutdown uses the reference to log in the destructor, you are accessing a 'dangling' reference, invoking undefined behavior and thus is seeing the problem.
And you have exactly the same problem with filename as well.
Obvious fix is to change write (which, by the way, is a terrible name for an object for several reasons) from being static to automatic variable.
This is called the static initialization order fiasco (which applies equally to destructors). It was always a problem, you just happened to get lucky earlier.
An easy way to fix that in your case is to change const char* filename; into std::string &filename; and MathHelper::Log& message; to MathHelper::Log message;. That way the memory will still be around by the time the destructor gets called.
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.
I'm working through some SDL2 tutorials and I just got up to a part where you start building a error logger. The entire code is:
void logSDLError(std::ostream &os, const std::string &msg){
os << msg << " error: " << SDL_GetError() << std::endl;
}
After awhile I realized what "std::ostream &os" did but I don't understand why the & and the const are necessary with the string. Why are they required? I know that if I don't use them it throws an error. In case it's important this is a snippet of the code that would use this function:
if (loadedImage != nullptr){
texture = SDL_CreateTextureFromSurface(ren, loadedImage);
SDL_FreeSurface(loadedImage);
//Make sure converting went ok too
if (texture == nullptr) logSDLError(std::cout, "CreateTextureFromSurface");
}
If your function header looks like this:
void testfunction(std::string msg), and you call it, it will be created a copy of the string thus taking up more space. If you want to either save memory or use the actual memory location of the string, you should do:
void testfunction(std::string &msg);
Although, this is dangerous when you do not want to modify the string, that's why one should use
void testfunction(const std::string &msg);
when you do not want to use any additional space, but you don't want the string to editable in the function.
Why are they required?
The const and & are used to pass the string message by constant reference so that you can save a copy of the string. The reference is to avoid the copy, and the const is to prevent you from edit it.
I know that if I don't use them it throws an error.
No, it won't throw any error related to the function argument.
I don't understand why the & and the const are necessary with the string.
& means you're passing by reference rather than value; const means the function can't use the reference to modify the string. Your introductory book should explain reference and value semantics in detail.
I know that if I don't use them it throws an error.
You could remove both (or just &) and pass by value without error; but that might be less efficient since the string will typically have to be copied.
If you remove const but leave & (passing by non-constant reference) then you wouldn't be able to pass a temporary string to the function, as your example does. Temporaries can only be bound to constant references.