I am looking at the following code ( simplified ) and ask myself how safe is it to use this returnMsg
function:
#include <iostream>
using namespace std;
const char *returnMsg(const char *msg)
{
static std::string message;
message = msg;
return message.c_str();
}
int main(int argc, char *argv[])
{
const char *msg1 = returnMsg("Hello world");
printf("msg1 = %p\n", msg1);
cout << msg1 << endl;
const char *msg2 = returnMsg("Good bye");
printf("msg2 = %p\n", msg2);
cout << msg2 << endl;
cout << msg1 << endl;
return 0;
}
the output is :
msg1 = 0x23a6028
Hello world
msg2 = 0x23a6028
Good bye
Good bye
msg2
is written twice and it's what i expected since the static message variable remains in memory during the lifetime of the program and there is no memory reallocation, so what is written at msg1
address is replaced by the new content of msg2
.
However if the size of msg2
is bigger, there is an internal reallocation within std::string message
variable and the output is :
msg1 = 0x1cc6028
Hello world
msg2 = 0x1cc6058
Good bye looooooooooooooooooooooooooooooooooooooooong
Hello world
but I guess that there is no guarantee that msg1
address will not be reused in the future, and so a new access to msg1
content might eventually display something different and not coherent.
Does this function needs to be written differently to make it possible to use it without the limitations shown above?
Is it safe to return a const char * from a function that use a static std::string internally?
Yes, that is safe.
But it is not safe to use that pointer after it has been invalidated, which is what the shown program does. The pointer will be invalidated by an assignment in a successive call to that function, if it reallocates. So, the pointer is safe only until the next call to the function (that would cause reallocation).
Does this function needs to be written differently to make it possible to use it without the limitations shown above ?
The function has the described limitations, so of course it has to be written differently to not have those limitations.
The core problem of your approach is that you only have one static string, but want to store multiple strings while not throwing away any of the earlier ones. So, it seems that you need a whole bunch of static strings:
const char *returnMsg(const char *msg)
{
static std::forward_list<std::string> messages;
messages.emplace_front(msg);
return messages.front().c_str();
}
While this works as you would expect, it is silly. Consider whether you really want to store all strings for the rest of the execution. If not, then static storage is not a solution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With