以安全的方式从char*创建std::string

10

我有一个指向以\0结尾的字符串的 char* p 变量,如何以安全的方式在C++中创建一个string

以下是一个不安全的版本:

string foo()
{
  char *p = get_string();

  string str( p );
  free( p );
  return str;
}

显然的解决方法是使用 try-catch - 是否有更简单的方法?

5个回答

25

你可以使用来自C++11Boostshared_ptr

string
foo()
{
    shared_ptr<char> p(get_string(), &free);
    string str(p.get());
    return str;
}

这里使用了shared_ptr的一个非常特定的功能,这个功能在auto_ptr或其他任何东西中都不可用,即指定自定义删除器的能力;在这种情况下,我使用free作为删除器。


是的,除非我们通常不使用Boost,但我可以自己创建这样一个类。谢谢 - n-alexander

3

您的示例中期望的异常是什么?

在许多平台(Linux、AIX)上,new或malloc永远不会失败,如果内存耗尽,应用程序将被操作系统杀死。

请参见此链接:Linux内存耗尽时会发生什么。


1

是的 - 基于堆栈的展开。《现代 C++ 设计》提供了一般解决方案,但在这种情况下,您可以使用

struct Cleanup {
        void* toFree;
        Cleanup(void* toFree) : toFree(toFree) {}
        ~Cleanup() { free(toFree); }
    private:
        Cleanup(Cleanup&);
        void operator=(Cleanup&);
};

无论你的std::string发生什么事情,当你的清理对象超出范围时,free(toFree)将被调用。

1

好的,如果get_string()返回NULL,则p不指向以0结尾的字符串;这就是问题所在,因为接受指向以0结尾的C字符串的std::string构造函数无法处理NULL,而NULL和两打香蕉一样都是以0结尾的C字符串。

因此,如果get_string()是您自己的函数(而不是库函数),那么也许您应该确保它不能返回NULL。例如,您可以让它返回所寻找的std::string本身,因为它知道自己的状态。否则,我会使用此答案中的Cleanup作为帮助程序来执行此操作,以确保p不会泄漏(如Martin York在评论中建议的那样)。

string foo()
{
    const char* p = get_string();
    const Cleanup cleanup(p);
    const std::string str(p != NULL ? p : "");

    return str;
}

除了代码无法编译(看看 L""),它还不具备异常安全性。您不能保证 p 将被释放。 - Martin York
啊!对不起 - 我只开发基于Windows CE的设备,那里我们只有Unicode字符串,所以当我编写代码时'L'前缀已经深入我的骨髓。现在这个问题已经解决了。 - Johann Gerell
哎呀,现在那个泄漏问题也解决了。感谢你指出来。 - Johann Gerell

0

我们通常在以下情况下使用ScopeGuard

string foo()
{
  char *p = get_string();
  ScopeGuard sg = MakeGuard(&free, p);
  string str( p );
  return str;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接