返回带有持久缓冲区的字符串

时间:2014-05-05 02:28:40

标签: c++ g++

我尝试编写一个将值格式化为字符串的函数。但是,我遇到了它的持久性问题。

using namespace std;

string string_format(const string &msg, ...)
{
    va_list ap;
    char text[BUFF_SIZE] = { 0, };
    va_start(ap, msg);
    vsnprintf(text, BUFF_SIZE - 1, msg.c_str(), ap);
    text[BUFF_SIZE - 1] = '\0';
    va_end(ap);

    return string(text);
}

int main()
{
    char* p1 = (char*)string_format("%d", 123).c_str();
    char* p2 = (char*)string_format("%d", 45).c_str();

    printf("value: p1=%s, p2=%s\r\n", p1, p2);
}

以上将打印:

  

值:p1 = 45,p2 = 45

而不是

  

值:p1 = 123,p2 = 45

我以这种方式编写代码,因为我想同时保留2个或更多char *实例。返回“new string(text)”有效,但我不想继续写“删除”

3 个答案:

答案 0 :(得分:2)

当您使用c_str()时,您将获得指向字符串中内部缓冲区的指针。只要字符串对象仍然存在,该指针才有效。您正在获取指向即时删除的临时字符串对象的指针,这会导致错误的行为。它表现为"持久性"可能是因为两个非常相似的字符串碰巧使用相同的内存空间。在任何情况下,在销毁字符串之后访问指针是未定义的行为。

如果您想使用c_str,则需要将生成的字符串存储到正确的string变量中,并在需要指针时将其保留在那里。

或者甚至更好,根本不处理char *。由于您正在使用C ++,因此请始终为字符串使用正确的字符串对象。

答案 1 :(得分:2)

将结果存储在string中,并在需要时使用.c_str()

string p1 = string_format("%d", 123);
string p2 = string_format("%d", 45);

printf("value: p1=%s, p2=%s\r\n", p1.c_str(), p2.c_str());

答案 2 :(得分:0)

感谢快速而明确的回复。为了实现我的原始目标(使我的代码更具可读性,因为这种缓冲区赋值在我编写的模块中很常见),我最终使用了一个声明字符串作为临时占位符的宏。这次它显示正确的结果

#define ASSIGN_BUFFER(var, format, value) \
    string str_##var = string_format(format, value) \
    var = (char*)str_##var.c_val()

string string_format(const string &msg, ...)
{
    va_list ap;
    char text[BUFF_SIZE] = { 0, };
    va_start(ap, msg);
    vsnprintf(text, BUFF_SIZE - 1, msg.c_str(), ap);
    text[BUFF_SIZE - 1] = '\0';
    va_end(ap);

    return string(text);
}

int main()
{
    char *p1, *p2;

    ASSIGN_BUFFER(p1, "%d", 123);
    ASSIGN_BUFFER(p2, "%d", 45);

    printf("value: p1=%s, p2=%s\r\n", p1, p2);
}