【问题标题】:C/C++ string memory leaks?C/C++ 字符串内存泄漏?
【发布时间】:2011-05-04 06:42:19
【问题描述】:

我在我的一个应用程序中使用 STL string,最近我正在测试它是否存在内存泄漏,我注意到我的很多字符串在程序结束时没有被正确地释放。

我用其中一个字符串测试了以下代码(不是逐字记录):

const string* cppString = &obj->objString;
const char* cString = cppString->c_str();
delete obj;

之后,我设置了一个断点并注意到,虽然 cppString 指向的 string 不再存在,但 cString 仍然指向一个 C 风格的字符串,这无疑是一个最后没有被释放的。

我是否遗漏了 C/C++ 字符串的工作方式?如何获得要释放的字符串的 C 表示形式?

编辑:更多信息。我的obj 类是Dialog 类型,它继承Popup。我以为可能是这样,因为当我删除obj 时,我将其视为Popup*,但我在一个单独的小型程序中尝试过,并且作为父类删除会正确删除子成员变量(当然,这是有道理的)。

我在 VS 中使用了内存泄漏跟踪,它表明最终泄漏的字符串是我创建 Dialog 并将 objString 设置为作为引用传递的字符串时创建的字符串构造函数。

谢谢,
詹格勒

【问题讨论】:

  • (糟糕,我之前的评论在阅读运算符优先级时出现了错误)。我认为您需要显示更多代码。在没有看到obj 的定义和分配方式的情况下,很难推测obj->objString 是否会被正确释放。
  • 这里看起来很乱,所以我将用我的评论更新 OP。
  • Popup 有虚拟析构函数吗?
  • @Adam:太棒了!当我在我的 OP 中进行编辑时,我怀疑它没有进行正确的析构函数调用,但是当我尝试将析构函数设为虚拟时,我可能做错了。我现在试了一下,效果很好。我会接受你的回复;您介意在您的回复中提及这一点,以便它可以帮助可能遇到此问题的其他人吗?

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


【解决方案1】:

您看到的是未定义的行为——它实际上并不是内存泄漏。 C 字符串 的内存已被释放(至少就您而言),但在技术上仍然可以访问那里的数据。当您释放内存时,内存通常不会被擦除,因此只要内存没有被后续分配重用,那里的数据通常会保留。

在数据被释放后读取数据是未定义的行为:您可能会得到释放前的数据,可能会收到垃圾数据,可能会导致程序崩溃,或者甚至可能会擦除硬盘驱动器(尽管这不是很可能)。

只要std::string 对象被正确释放,用于其C 字符串表示的任何内存也将被释放。你不必担心这个。


编辑:实际上你的对象并没有被销毁,因为父类Popup 没有虚拟析构函数。结果,子类Dialog 的析构函数没有被调用,所以std::string 实例的析构函数也没有被调用。

【讨论】:

  • 这是有道理的,但我使用了 Visual Studio 的内存泄漏检测程序(它基本上遵循所有 mallocfree 调用)并且当我在末尾转储内存泄漏信息时该程序,该字符串,在类似位置的字符串中,显示为未正确释放。
【解决方案2】:

问题很可能不在std::string,而在obj(无论是什么类型)。请注意,您删除了obj,而不是cppString。我的猜测是obj 不会将objString 存储在智能指针类中,也不会在其析构函数中删除objString,因此您有泄漏。

【讨论】:

  • objString是正则字符串,不是指针,所以应该被默认析构函数自动删除,不是吗?
  • @Jengerer,你从 objString 分配到类型“const string*”,而不是类型“const string”,所以它必须是指针类型,除非你与我们共享不同的代码。
  • 我的意思是在对象类中,objStringstring 类型而不是指针。当我把它分配给const string*时,我做了&obj->objString,所以我使用&运算符来获取地址。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-19
  • 1970-01-01
  • 1970-01-01
  • 2011-05-14
  • 2014-04-30
  • 1970-01-01
  • 2016-01-27
相关资源
最近更新 更多