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

时间:2008-10-29 11:22:37

标签: c++ exception

我有一个char* p,它指向一个以\0结尾的字符串。如何以异常安全的方式从中创建C ++ string

这是一个不安全的版本:

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

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

一个明显的解决方案是尝试捕捉 - 任何更简单的方法?

5 个答案:

答案 0 :(得分:25)

您可以使用C++11Boost中的shared_ptr

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

这使用shared_ptr中的auto_ptr特有的非常具体的功能,或其他任何功能,即指定自定义删除器的功能;在这种情况下,我使用free作为删除者。

答案 1 :(得分:3)

我可以问你在你的例子中期待什么例外吗?

在许多平台上(Linux,AIX),如果你的内存不足,new或malloc将永远不会失败,你的应用程序将被os杀死。

请参阅此链接:What happens when Linux runs out of memory.

答案 2 :(得分:1)

Yup - 基于堆栈的展开。 Modern C ++ Design有一般解决方案,但在这种情况下你可以使用

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

无论你的std :: string发生了什么,当你的Cleanup对象超出范围时,都会调用free(toFree)。

答案 3 :(得分:1)

好吧,p如果get_string()返回NULL,则不会指向以0结尾的字符串;这就是问题,因为std::string构造函数接受指向0终止的C字符串的指针不能处理NULL,这是一个0终止的C字符串,就像两个数十个香蕉一样。

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

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

    return str;
}

答案 4 :(得分:0)

对于这些情况,我们通常使用ScopeGuard

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