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