【问题标题】:Assigning to dereferenced string -- can this cause a memory leak?分配给取消引用的字符串——这会导致内存泄漏吗?
【发布时间】:2016-11-13 22:59:21
【问题描述】:

这里是 C++ 新手。以下是否会导致内存泄漏?

// debug is optional, for debugging purposes.
// Say my_string is an internal string class my company uses.

int DoSomething(my_string *debug) {
  const my_string& s = GetString();
  if (debug != nullptr) *debug = s;  // Could this cause a memory leak?
  return DoSomethingElse(s);
}

我想在这里检查我的理解:我认为在注释行中,debug 指向的内存区域将被s 的内容(副本)覆盖,除非有副本-为my_string 实现的构造函数,在这种情况下它也可能做一些其他的事情。

如果my_string 没有特殊的复制构造函数,那么如果my_string 在其内部表示中指向任何动态分配的内存(它可能会这样做,因为它可以保存任何长度的字符串),那么上面代码会导致内存泄漏。

另外,我猜还有一个关于预期 C++“礼仪”的问题——我是否可以假设写my_string 的人写了一个复制构造函数以避免在这种情况下发生内存泄漏?也就是说,由于我自己的代码中没有任何new,如果这段代码导致内存泄漏,是否可以合理地说这不是我的“错”?

编辑:我想也许我的意思是上面的复制赋值运算符而不是复制构造函数。

【问题讨论】:

  • my_string 最好有一组单元测试来验证它不会泄漏,并且有一个使用它的好理由,而不是std::string .当然,这可能会泄漏my_string 很烂。最终,如果您知道它很糟糕并且仍然使用它,那么是的,可以说它仍然是您的错。
  • 也许是,也许不是。这取决于此处未显示的代码。
  • @WhozCraig @juanchopanza 是只依赖my_string的实现还是也依赖GetStringDoSomethingElse

标签: c++ memory-management memory-leaks


【解决方案1】:

理论上这可能是内存泄漏。但是,每当您编写一个内部管理任何类型资源的类时(我们经常这样做),请始终尊重The Rule of FiveRAII。我的意思是,如果编写 my_string 类的人是理智的,他们明确定义了复制运算符,因此泄漏永远不会发生。

另外,如果您不完全了解复制构造函数和复制运算符之间的区别,this question 可能会有所帮助。

【讨论】:

    【解决方案2】:

    答案完全取决于my_string operator=(const my_string& s) 的作用。如果他们引用了您创建的本地临时字符串所拥有的内存,那是他们的错。如果你知道的话,也是你的。在这种情况下,它可能会崩溃。

    另一方面,如果他们对您传递给 operator= 的字符串进行了深层复制,那么一切都很好,当您的本地字符串超出范围时,一切正常。

    您不应该担心内存泄漏,而应该担心字符串 debug 中可能存在悬空指针。

    【讨论】:

      【解决方案3】:

      是的,这是你的错,使用你知道不好的代码总是你的错。修复它或使用大量 cmets 解决它,但永远不要假装它是别人的问题。

      代码不会泄漏,但它可能会崩溃。

      发生的情况是你返回了一个指向字符串的指针,但是当你离开函数时,原来的字符串内存被删除了。现在通常内存会在短时间内保持完整,但迟早(通常更快)其他东西会使用字符串曾经占用的内存,并且您充其​​量是垃圾,最坏的情况是崩溃。

      您会注意到从 GetString 返回的 my_string 可能会创建一个临时副本(您尚未显示代码),因此 s 将指向该临时对象。如果 GetString 返回指向原始字符串的指针,那么您就处于更安全的位置,但现在您将受制于拥有 GetString 返回的原始字符串的任何人。

      返回一个被复制的字符串对象并返回副本(编译器会对此进行很好的优化,以便您获得最少的内存副本)或返回一个 shared_ptr 以便您可以更好地处理所有权。

      【讨论】:

        猜你喜欢
        • 2011-11-09
        • 2021-05-01
        • 1970-01-01
        • 1970-01-01
        • 2020-04-06
        • 1970-01-01
        相关资源
        最近更新 更多