【问题标题】:Memory Freeing Inqury内存释放查询
【发布时间】:2011-01-23 06:53:06
【问题描述】:

另外感谢 Daniel Newby 回答我的内存使用问题(以及 Martin York 的更多解释)。这绝对是我一直在寻找的答案,但我的其他问题更多是由其他人回答的。

谢谢大家

为了解决我所有的疑虑。很高兴看到事情按照我的预期运行。

我遇到了一些我不确定的事情。

在我的程序中,我没有使用malloc() free()。我正在使用new创建我的类的实例,并且我确保每个运行它的destructor 当它是delete'd,但是,没有free() 调用或甚至将它们的指针(指向全局范围内的事物或其他类)设置为 NULL0

我所说的“我已经确定”并不是我调用每个析构函数。我只使用delete来调用析构函数来运行,但是每次创建对象时变量都会增加1,并且每次运行析构函数时都会增加1。这就是我确保创建的对象数量等于调用的析构函数数量的方法。

我应该使用malloc()free() 吗?我应该NULLing 指向我仍然想存在的东西吗?

第二个问题是,为什么当我查看我的任务管理器时,我的进程永远不会“丢弃”内存?它曾经永远不会停止获得,然后我开始deleting一切正常。或者我是这么想的。

free()delete 不会降低内存使用率吗?

我应该对malloc'ing 和free'ing 使用链表的内存进行哪些实践?

【问题讨论】:

  • “我已经确保每个都运行它的析构函数”是什么意思。你不是在调用析构函数吗?
  • 不,我刚刚在它的析构函数中添加了一个增量,以便看到每个被创建的函数也会在删除时调用其析构函数。
  • 这句话吓到我了:我已经确保每个人在删除时都运行它的析构函数你能解释一下你在做什么吗?
  • 在大多数操作系统上。应用程序永远不会将内存释放回操作系统(直到它退出)。因此,如果您使用某些操作系统工具来检查内存,它看起来永远不会崩溃。在内部,您的应用程序会跟踪释放的内存,以便下一个 malloc/new 重新使用它,从而减少应用程序从操作系统请求的内存量。
  • 例如,当我关闭和打开新标签页时,firefox 的内存会上下波动。即使我清除所有数据,Photoshop 也不会减少。因此,在 Windows 上运行的程序似乎可以减少内存使用量。

标签: c++ memory-management pointers


【解决方案1】:

在我的程序中,我没有使用 malloc() 或 free()。我正在使用 new 创建我的类的实例,并且我确保每个类在删除时都运行它的析构函数,

这太可怕了。你不需要让任何东西运行它的析构函数。它被分配(new)它被销毁(delete)构造函数在new上原子地运行,而析构函数在delete时自动运行。

但是,没有 free() 调用,甚至没有将它们的指针(指向全局范围内的事物或其他类)设置为 NULL 或 0。

没有必要在 C++ 代码中使用 malloc/free(在某些情况下,您使用的 C 库需要 malloced 内存,但它们已明确记录且很少)。

从技术上讲,删除后不需要将指针设置为 NULL。
变量在被删除后立即超出范围是一种很好的技术,因此它不会被意外重用。如果由于某种原因,在调用 delete 后指针变量存在很长时间(即不会超出范围),那么将其设置为 NULL 是很有用的,这样它就不会被意外重用。

我还是应该使用 malloc() 和 free() 吗?我是否应该将指向我仍然希望存在的事物的指针归零?

没有和没有。
注意:与 Java 不同,C++ 不会跟踪有多少指针指向一个对象。
如果您有多个指针指向一个对象,则需要使用智能指针(无论如何您都应该使用智能指针)。

第二个问题是,为什么当我查看任务管理器时,我的进程永远不会“丢弃”内存?它曾经永远不会停止获得,然后我开始正确删除所有内容。或者我是这么想的。

应用程序永远不会释放回操作系统(在正常情况下在大多数操作系统上)。
所以内存永远不会下降(直到应用程序退出)。
内存管理在内部跟踪所有空闲,以便可以重新使用内存。 但是如果它用完了,它会向操作系统询问更多,因此在任务管理器中,内存分配会增加(这不会返回给操作系统)。

free() 或 delete 不会降低内存使用率吗?

没有。

对于链表的 malloc'ing 和 free'ing 内存,我应该采取哪些做法?

您应该使用智能指针,这样您就不必担心何时删除对象。
它们还使您的代码异常安全。

但是如果你使用指针。调用 delete 来删除一个元素,然后将其值设置为 NULL(在调用 delete 之后,指针作用域仍然存在很长时间)。

注意:boost:shared_pointer 与 Java 指针非常相似。它跟踪指针的数量并在对象的最后一个引用被销毁时删除该对象。您无需进行任何删除操作(就像 Java 一样),您真正需要做的就是调用 new(就像 Java 一样)。

【讨论】:

    【解决方案2】:

    “我还是应该使用 malloc() 和 free() 吗?”

    不,在大多数情况下。只坚持一种形式的内存管理。尝试同时使用这两种方法意味着您将不可避免地搞砸并删除一个 malloc() ed 项,或 free() 一个 new 项,从而产生一个微妙的错误。坚持使用一种形式,您就可以提前修复这些错误。

    “free() 或 delete 不会降低内存使用率吗?”

    操作系统以为单位分配内存,通常大小为 4 kiB。只要页面的单个字节仍在使用中,它就不会返回给操作系统。您可能正在分配许多小项目,但并未释放所有小项目。 (有一些方法可以帮助自定义新建/删除,但它们通常不值得。)

    【讨论】:

    • 谢谢。一些测试,这绝对是我正在寻找的答案。如果可以的话,我会投票。
    【解决方案3】:

    您应该将deletenewfreemalloc 一起使用。 delete 将调用类的析构函数,因此您不必显式调用它。析构函数的目的是释放类可能拥有的资源,delete 也会释放内存。

    您应该明确使用析构函数的唯一时间是当您通过placement new 初始化您的对象时。你应该把自己置于编译器生成的代码释放你的资源的位置——阅读这篇关于 C++ 习语的文章:resource acquisition is initialization

    同样将类的指针设置为 null 也无济于事,后台没有垃圾收集器来清理你的内存。如果您不在 C++ 中释放动态内存,它将被“泄漏”内存——即,没有指向内存的链接,并且在进程退出之前永远不会被回收。

    p.s.,再次不要混合内存分配函数对。

    edt:不要实现链表,使用标准模板库提供的容器。如果您觉得需要更好的性能,请使用 boost 中的 intrusive containers

    【讨论】:

    • 我会确保从现在开始使用其中一个。谢谢。
    【解决方案4】:
    1. new 和 delete 或多或少可以被视为 malloc 和 free 的 C++ 版本。所以坚持一对或另一对,即如果一个指针是用new创建的,它应该用delete释放,这样可以确保你提到的析构函数调用。 malloc/free 对不支持 C++,只是分配和释放一块没有附加构造函数/析构函数语义的内存。

    2. 是的,我确实认为当指针被释放或删除时将指针设置为 NULL 或零是一种很好的形式。在调试过程中,我有时也会将它们设置为 0xdeadbeef 之类的特征,以便它们脱颖而出。

    3. 很可能操作系统“内存使用情况”反映了进程堆的整个大小,而不是内存管理器对分配多少内存的想法。当分配器发现它没有足够的堆空间时,它会增加堆,这将反映在您正在查看的“内存使用情况”中。理论上,可以在内存释放时相应地缩小堆,但这并不总是发生。因此,您可能只会看到内存使用量增加,而不会减少。

    【讨论】:

    • 感谢您解释为什么我的内存使用量没有减少。我会看看我是否能弄清楚如何做到这一点。
    【解决方案5】:

    您应该优先使用 new 和 delete,而不是 malloc()/calloc()/realloc() 和 free()。

    如果您要创建链接列表,您应该使用std::list. 另外,请查看std::vector

    就您的应用程序的明显内存使用而言:很有可能在应用程序退出之前内存不会返回到系统。

    【讨论】:

      【解决方案6】:

      很少有理由在 C++ 程序中使用 malloc()free()。坚持使用newdelete。请注意,与具有垃圾收集的语言不同,在 C++ 中将指针设置为 NULL 或 0 与释放内存无关。

      【讨论】:

      • 我很难摆脱使用 malloc 和 free 处理非类数据的习惯。
      • 你应该试着改掉这个习惯。如果您使用 malloc 和 free 来创建动态数组,请改用 vector。
      • 重新运行:记住结构是类。
      • @rerun:类甚至不是重点。重点在于 POD 数据与非 POD 数据,这对于 C++ 新手甚至中等 C++ 编码人员来说都是微不足道的。
      • @phresnel 意思是如果我正在分配一个字符数组 malloc 和 calloc 接缝来滚动我的手指。如果我正在使用具有构造函数的东西,我会自动使用 new。
      猜你喜欢
      • 2013-06-21
      • 2011-05-10
      • 2011-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-12-23
      • 2013-12-05
      相关资源
      最近更新 更多