我正在查看以下代码(简化)并问自己使用returnMsg函数有多安全:
#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; }
输出是:
msg1 = 0x23a6028 Hello world msg2 = 0x23a6028 Good bye Good bye
msg2写了两次,这是我所期望的,因为静态消息变量在程序的生命周期内保留在内存中,并且没有内存重新分配,因此msg1地址处写的内容被msg2的新内容替换.
但是,如果msg2的大小较大,则std :: string消息变量中存在内部重新分配,输出为:
msg1 = 0x1cc6028 Hello world msg2 = 0x1cc6058 Good bye looooooooooooooooooooooooooooooooooooooooong Hello world
但我想无法保证msg1地址将来不会被重用,因此对msg1内容的新访问可能最终会显示不同的内容而不是连贯的.
这个功能是否需要以不同的方式编写才能在没有上述限制的情况下使用它?
解决方法
Is it safe to return a const char * from a function that use a static std::string internally?
是的,那是安全的.
但是在指针失效后使用该指针是不安全的,这就是所示程序的作用.如果重新分配,则在对该函数的连续调用中的赋值将使指针无效.因此,指针在下一次调用函数之前是安全的(这将导致重新分配).
Does this function needs to be written differently to make it possible to use it without the limitations shown above ?
该功能具有所描述的限制,因此当然必须以不同的方式编写以不具有这些限制.
你的方法的核心问题是你只有一个静态字符串,但想要存储多个字符串而不丢弃任何早期字符串.所以,似乎你需要一大堆静态字符串:
const char *returnMsg(const char *msg) { static std::forward_list<std::string> messages; messages.emplace_front(msg); return messages.front().c_str(); }
虽然这可以像你期望的那样工作,但这很愚蠢.考虑是否确实要为执行的其余部分存储所有字符串.如果没有,那么静态存储不是解决方案.