C、C++ 中的内存泄漏;忘了做免费,删除

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1232262/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 19:15:27  来源:igfitidea点击:

Memory leak in C,C++; forgot to do free,delete

c++c

提问by seg.server.fault

We allocate memory in C using malloc and in C++ using new. I know that memory allocated must be freed or given back to OS using free in C and delete in C++. If I forgot to use free/delete after allocating memory, it means there will be memory leak.

我们在 C 中使用 malloc 分配内存,在 C++ 中使用 new 分配内存。我知道必须使用 C 中的 free 和 C++ 中的 delete 释放分配的内存或将其返回给操作系统。如果我在分配内存后忘记使用 free/delete,则意味着会有内存泄漏。

Now, my question is, is this memory leak only during the time period of execution of program; or is it permanent leak/loss or is it gained again once I restart the system ? What is the internal process actually ? What does memory leak/loss mean exactly?

现在,我的问题是,这种内存泄漏是否仅在程序执行期间?或者它是永久性泄漏/丢失还是在我重新启动系统后再次获得?内部流程究竟是怎样的?内存泄漏/丢失究竟是什么意思?

I would be very grateful if someone could explain this in detail or provide me with some nice references.

如果有人能详细解释这一点或为我提供一些不错的参考资料,我将不胜感激。

UPDATE 1

更新 1

After reading some answers, I learnt that memory is given back to OS/system after program terminates, if that is so, why everyone needs to care so much about memory leak, and why preventing memory leak is very important ?

看了一些答案,我了解到程序终止后内存会归还给操作系统/系统,如果是这样,为什么每个人都需要如此关心内存泄漏,为什么防止内存泄漏很重要?

UPDATE 2

更新 2

So, memory leak should be prevented so that the system doesn't crash due to lack of sufficient memory for allocation purposes ??

因此,应该防止内存泄漏,以便系统不会因分配内存不足而崩溃??

UPDATE 3

更新 3

So, after reading all answers, I realized that memory leak is quiet important issues to prevent system crashes. But, for a beginner like me, how can I be sure if my program is completely free from memory leak. I try to do free,delete if I am using malloc,new but sometimes, it gets messy. Is there any tool or method which I can use to know if my program is doing any memory leak ?

因此,在阅读所有答案后,我意识到内存泄漏是防止系统崩溃的重要问题。但是,对于像我这样的初学者,我如何确定我的程序是否完全没有内存泄漏。我尝试免费,如果我使用 malloc,则删除,新但有时,它会变得混乱。有什么工具或方法可以让我知道我的程序是否有内存泄漏?

UPDATE 4

更新 4

After reading answers, I have now understood the importance of memory leak free code, less use of new/delete, more use of STL, learnt new stuffs like RAII,valgrind and good programming practices. Thanks to all :)

阅读答案后,我现在了解了无内存泄漏代码的重要性,更少使用 new/delete,更多使用 STL,学习了 RAII、valgrind 等新东西和良好的编程实践。谢谢大家 :)

采纳答案by Brian Agnew

It's per-process. Once your process exits, the allocated memory is returned to the OS for use by other processes (new or existing).

这是每个进程。一旦您的进程退出,分配的内存将返回给操作系统供其他进程(新的或现有的)使用。

To answer your edited question, there's only a finite amount of memory in your machine. So if you have a memory leak, then the major problem is that the memory isn't available for otherprocesses to use. A secondary, but not negligible, effect is that your process image grows, you'll swap to disc and performance will be hit. Finally your program will exhaust all the memory in the system and fail, since it's unable to allocate any memory for itself.

要回答您编辑的问题,您的机器中只有有限的内存量。因此,如果您有内存泄漏,那么主要问题是该内存不可用于其他进程。次要但不可忽略的影响是您的过程映像增长,您将切换到磁盘并且性能将受到影响。最后,您的程序将耗尽系统中的所有内存并失败,因为它无法为自己分配任何内存。

It's arguable that for a small process with a short lifetime, memory leaks are tolerable, since the leaked memory will be small in quantity and short-lived.

可以说,对于一个生命周期短的小进程来说,内存泄漏是可以容忍的,因为泄漏的内存数量少,生命周期短。

Take a look at this resource, for possibly more info than you'll ever need. What we're discussing here is dynamicor heapallocation.

查看此资源,可能会获得比您需要的更多信息。我们在这里讨论的是动态分配或分配。

回答by jalf

A memory leak simply means that your applicationfails to release memory it has allocated. Once your program ends, it is up to the OS what happens. Every modern OS will reclaim all memory used by the application, so once your process terminates, it'll get cleaned up.

内存泄漏只是意味着您的应用程序无法释放它已分配的内存。程序结束后,由操作系统决定会发生什么。每个现代操作系统都会回收应用程序使用的所有内存,因此一旦您的进程终止,它将被清理。

But C/C++ do not guaranteethat the OS does that. It is possible on some platforms that the memory stays lost until you reboot.

但是 C/C++ 不保证操作系统会这样做。在某些平台上,内存可能会一直丢失,直到您重新启动。

So the problem with memory leaks is twofold:

所以内存泄漏的问题是双重的:

  • one a few platforms the system might have to reboot to reclaim the memory. On most platforms this is a non-isssue, although leaking some other resource types may still cause problems.
  • As long as your program is running, it will allocate memory it never frees, which means it'll use more and more memory. If your program is intended to run for a long time, it may end up using all the available memory on the machine, and subsequently crash.
  • 系统可能必须重新启动才能回收内存的少数平台之一。在大多数平台上,这不是问题,尽管泄漏一些其他资源类型可能仍然会导致问题。
  • 只要您的程序在运行,它就会分配永远不会释放的内存,这意味着它将使用越来越多的内存。如果您的程序打算长时间运行,它最终可能会使用机器上的所有可用内存,并随后崩溃。

Many short-running programs actually ignore memory leaks becausethey know it'll get cleaned up by the OS soon enough. Microsoft's C++ compiler does this, as far as I know. They know that once the compiler is invoked, it runs for a couple of minutes at the most. (and they know it runs on Windows, where the OS doesreclaim memory once the process terminates) So it's ok that it leaks some memory here and there.

许多短时间运行的程序实际上忽略了内存泄漏,因为它们知道操作系统很快就会清除它。据我所知,微软的 C++ 编译器就是这样做的。他们知道,一旦调用编译器,它最多会运行几分钟。(他们知道它运行在Windows,其中OS确实回收存储过程一旦终止的),所以没关系,它在这里和泄漏一些内存出现。

As for how to avoid memory leaks, don't create them.

至于如何避免内存泄漏,就不要创建了。

You risk leaking memory every time you use new/delete, so don't.

每次使用 new/delete 时都有泄漏内存的风险,所以不要.

When you need an array of data do this:

当您需要一组数据时,请执行以下操作:

std::vector<char> vec(200);

instead of this:

而不是这个:

char* arr = new char[200];

The former is just as efficient, but you don't have to explicitly call delete to free it std::vectoruses RAII to manage its resources internally. And you should do the same -- either by using ready-made RAII classes like vector, shared_ptr, or almost any other class in the standard library or in Boost, or by writing your own.

前者同样高效,但您不必显式调用 delete 来释放它,它std::vector使用 RAII 在内部管理其资源。你应该做同样的-无论是使用像现成的RAII类vectorshared_ptr或几乎任何其他标准库或升压级,或通过编写自己的。

As a general rule of thumb, your code should not contain any new/delete calls, exceptin the constructor/destructor for the class responsible for managing that allocation.

作为一般经验法则,您的代码不应包含任何 new/delete 调用,除了负责管理该分配的类的构造函数/析构函数。

If an object allocates the memory it needs in the constructor, and releases it in the destructor (and handles copying/assignment correctly), then you can simply create a local instance of the class on the stack whenever you need it, and it will not, can not, leak memory.

如果一个对象在构造函数中分配了它需要的内存,并在析构函数中释放它(并正确处理复制/赋值),那么你可以在需要的时候简单地在堆栈上创建一个类的本地实例,它不会,不能,内存泄漏。

The key to not leaking memory in C++ is to not call new/delete.

在 C++ 中不泄漏内存的关键是不调用 new/delete。

回答by jcoder

The operating system will track memory and once your program terminates will reclaim all the memory. It just means that your application lost track of some allocated memory.

操作系统将跟踪内存,一旦您的程序终止将回收所有内存。这只是意味着您的应用程序丢失了某些已分配内存的跟踪。

Note that this might not apply on some operating systems but will be the case on any windows/unix/mac type system

请注意,这可能不适用于某些操作系统,但适用于任何 windows/unix/mac 类型系统

回答by Shawn Chin

Re: tools to detect memory leak

Re: 检测内存泄漏的工具

If you use a Linux based OS for development, you can try using valgrind (http://valgrind.org/) to detect memory leak.

如果您使用基于 Linux 的操作系统进行开发,您可以尝试使用 valgrind ( http://valgrind.org/) 来检测内存泄漏。

valgrind --leak-check=full ./compiled_binary

If you program was compiled with debug symbols (e.g. for gcc, include the -g flag), valgrind will also inform your of the exact line of code where the leaked memory was allocated. This will greatly ease the task of tracking and fixing leaks.

如果您的程序是用调试符号编译的(例如,对于 gcc,包括 -g 标志),valgrind 还会通知您分配泄漏内存的确切代码行。这将大大简化跟踪和修复泄漏的任务。

Pros: it is free

优点:它是免费的

Cons: AFAIK, it only works on Linux

缺点:AFAIK,它只适用于 Linux

Update

更新

As seen on http://valgrind.org/info/platforms.html, valgrind is being ported to other OSes (and platforms) include MacOSX, FreeBSD and NetBSD.

正如在http://valgrind.org/info/platforms.html 上看到的,valgrind 正在被移植到其他操作系统(和平台),包括 MacOSX、FreeBSD 和 NetBSD。

Update 2

更新 2

(slightly off topic but...)

(有点跑题了,但是……)

The good thing about using valgrind is that it does a lot more than just checking for memory leaks. See http://valgrind.org/info/tools.html

使用 valgrind 的好处是它不仅仅检查内存泄漏。见http://valgrind.org/info/tools.html

I configured buildbot to run valgrind (and splint) against all my nightly builds, and that has proven invaluable!

我将 buildbot 配置为对我所有的夜间构建运行 valgrind(和夹板),这已被证明是无价的!

回答by Ran Halprin

There are tools to detect memory leaks, e.g. Purify.

有一些工具可以检测内存泄漏,例如Purify

回答by John Deters

As a new to C++ programmer, the best advice I could give to you would be to learn how to minimize the number of "new" and "delete" statements you write. If you have the compiler create your objects locally on the stack, it will manage the memory for you, deleting the objects automatically as they go out of scope.

作为 C++ 程序员的新手,我能给你的最好建议是学习如何最大限度地减少你编写的“new”和“delete”语句的数量。如果您让编译器在堆栈上本地创建对象,它将为您管理内存,并在对象超出范围时自动删除它们。

There is a programming idea called Resource Acquisition Is Initialization (RAII). What this says is "if you need to allocate memory that needs to be deleted, or make sure that stuff you open gets closed, wrap it in an object that you create on the stack. That way when the object goes out of scope the destructor automatically gets invoked, and you delete your resource in the destructor."

有一种编程思想叫做资源获取即初始化(RAII)。这说的是“如果您需要分配需要删除的内存,或者确保您打开的东西被关闭,请将其包装在您在堆栈上创建的对象中。这样当对象超出析构函数的范围时自动被调用,然后您在析构函数中删除您的资源。”

Common memory leaks happen when you write a "new" in the code, but your function exits before you call delete. Sometimes you encounter a "return" statement too early, other times an exception gets thrown and caught after your "delete" statement. Following RAII helps you make sure those accidents don't happen.

当您在代码中编写“new”时会发生常见的内存泄漏,但您的函数在调用 delete 之前退出。有时您会过早地遇到“return”语句,有时会在“delete”语句之后抛出并捕获异常。遵循 RAII 可帮助您确保不会发生这些事故。

回答by Artyom

Several points to add:

补充几点:

  1. Learn to work correctly form the beginning-- free memory, it is very hard to fix bad habit.
  2. Memory is not the unique resource that should be managed or managed using new/delete.

    For example, some object may hold some temporary file that should be deleted on the end. Usually such things are binded to some object, so, if your forget to delete object, you forget to unlink the file and... This resource does not come back even with system restart.

    There lots of other similar resources that binded to objects and managed with new/delete: files, sockets, shared memory, database connections and so on. So, all the techniques you learn to manage memory would help you to manage these other, much limited resources that you would have to use.

  1. 从一开始就学会正确工作——释放内存,改掉坏习惯很难。
  2. 内存不是应该使用 new/delete 管理或管理的唯一资源。

    例如,某个对象可能保存了一些应该在最后删除的临时文件。通常这样的东西被绑定到某个对象,所以,如果你忘记删除对象,你忘记取消链接文件......即使系统重新启动,该资源也不会回来。

    还有许多其他类似的资源绑定到对象并使用 new/delete 进行管理:文件、套接字、共享内存、数据库连接等。因此,您学习管理内存的所有技术都将帮助您管理您必须使用的其他非常有限的资源。

回答by gbjbaanb

Update 1:
If you have a simple app that runs once, does its thing and terminates, then a memory leak isn't so important. Its still a very bad practice and if you're coding style is such that you allow leaks in your code at all, then you will probably put the same leaks into apps where it is important - ones that work for days, weeks or years. We have an app here that leaks, so we restart it every month. Its not an ideal situation.

更新 1:
如果您有一个简单的应用程序,它运行一次,执行它的操作并终止,那么内存泄漏并不是那么重要。这仍然是一种非常糟糕的做法,如果您的编码风格完全允许代码泄漏,那么您可能会将相同的泄漏放入重要的应用程序中 - 那些可以工作数天、数周或数年的应用程序。我们这里有一个应用程序会泄漏,所以我们每个月都会重新启动它。它不是一个理想的情况。

Update 2:
yes, pretty much. But memory leaks should be prevented simply because they are a bug, and you should never write code with a view that bugs are acceptable.

更新 2:
是的,差不多。但是应该防止内存泄漏仅仅因为它们是一个错误,并且您永远不应该以错误是可以接受的观点编写代码。

Update 3:
The best way to prevent memory leaks is not to use malloc/free in the first place. If you're using C++ read up on RAII, use classes and copy the objects about, this will ensure you never have leaks... nearly all the time. If you do have to allocate memory explicitly, then make sure you keep track of it. If that means you need a global object somewhere that you store the pointers, then do so. If it means you have a collection class that stores the pointers, then get one. Never allocate memory to a local variable that you might forget about, might return from a function without going over the free call, might pass to another function to free that doesn't get called. A sense of discipline is needed for this (not much discipline is required), but many people will tell you that that same virtue is required to write good, correct, well designed, bug-free code anyway (and they'd be right - if you've ever seen hacked together code compared to well designed code, you'll be able to see the difference immediately).

更新 3:
防止内存泄漏的最佳方法是首先不要使用 malloc/free。如果您在 RAII 上使用 C++ 阅读,使用类并复制对象,这将确保您永远不会泄漏......几乎所有时间。如果确实必须显式分配内存,请确保对其进行跟踪。如果这意味着您需要一个全局对象来存储指针,那么就这样做。如果这意味着您有一个存储指针的集合类,则获取一个。永远不要将内存分配给您可能会忘记的局部变量,可能会从函数返回而不通过 free 调用,可能会传递给另一个没有被调用的函数以释放。为此需要一种纪律感(不需要太多纪律),但很多人会告诉你,同样的美德也需要写出好的、正确的、精心设计的,

Notes:
even using a garbage collected language you will still get memory leaks. People add objects to collections, then forget to remove them, and so the object remains in memory forever. That counts as a leak. Its reasonably common in GC languages to do this as people think the GC will do all the work for them. Again, coding/design discipline is required - know what you're doing will prevent these bugs.

注意:
即使使用垃圾收集语言,您仍然会遇到内存泄漏。人们将对象添加到集合中,然后忘记删除它们,因此对象永远保留在内存中。这算作泄漏。在 GC 语言中这样做是很常见的,因为人们认为 GC 会为他们做所有的工作。同样,编码/设计纪律是必需的——知道你在做什么将防止这些错误。

Memory leaks can occur even without using malloc/new. Be aware of overwriting pointer variables that already point to some memory. My biggest ever source of leaks was with MSXML, I'd create a CComPtr of a XML object, then call the method to get an element, passing the object in to the method as a parameter. Unfortunately the class was cast to the internal pointer and the method would just overwrite it with the new pointer, leaving the old data leaked. The moral here is that, if using a smart pointer class, make sure you know what its doing, especially with its cast operator.

即使不使用 malloc/new,也可能发生内存泄漏。注意覆盖已经指向某些内存的指针变量。我有史以来最大的泄漏源是使用 MSXML,我创建了一个 XML 对象的 CComPtr,然后调用该方法来获取一个元素,将该对象作为参数传递给该方法。不幸的是,该类被强制转换为内部指针,该方法只会用新指针覆盖它,从而导致旧数据泄漏。这里的寓意是,如果使用智能指针类,请确保您知道它在做什么,尤其是它的强制转换运算符。

Tools:
you don't need to buy Purify if running on Windows. Microsoft offers UMDHwhich takes snapshots of your memory. Take 2 snapshots and compare them using the tool, and you can see allocations that steadily increase over time without being de-allocated. Its not pretty, but it works.

工具:
如果在 Windows 上运行,则无需购买 Purify。Microsoft 提供了UMDH,它可以对您的内存进行快照。拍摄 2 个快照并使用该工具进行比较,您可以看到分配随着时间的推移稳步增加而不会被取消分配。它不漂亮,但它有效。

回答by Mike McQuaid

It's a memory leak.

这是内存泄漏。

Basically what it means is that this memory won't be reclaimed until the process is destroyed.

基本上这意味着在进程被销毁之前不会回收这些内存。

The problem is when the pointer goes out of scope and you don't free the memory then it is allocated by the process but there is no way of the program knowing that it is out of scope and no longer needed (without using a tool like Valgrind).

问题是当指针超出范围并且您不释放内存时,它由进程分配,但程序无法知道它超出范围并且不再需要(不使用类似的工具)瓦尔格林)。

This is only a major problem if it happens repeatedly. If it does then the program will keep using more and more memory the longer it runs before eventually crashing. Users will need to restart the application regularly to avoid this happening or it using too many system resources.

如果它重复发生,这只是一个主要问题。如果是这样,那么程序在最终崩溃之前运行的时间越长,它就会继续使用越来越多的内存。用户需要定期重新启动应用程序以避免这种情况发生或使用过多的系统资源。

回答by mmmmmmmm

The memory will not be lost but it stays allocated and so isn't available for the next allocations your program does. This means that your program consumes more and more memory if it continues to allocate memory without deallocating it. After a while there is non unallocated memory left and the next attempt to allocate new memory will fail so your program does.

内存不会丢失,但它会保持分配状态,因此不可用于您的程序进行的下一次分配。这意味着如果你的程序继续分配内存而不释放它,它会消耗越来越多的内存。一段时间后,剩下未分配的内存,下一次分配新内存的尝试将失败,因此您的程序也会失败。

This memory is taken from the so-called "heap". Which is local to your program and is completely removed when your program finishes. So the "only" harm your program can do to the other programs running in the system and the OS is that they may also be unable to allocate memory because your program has "eaten up" all. As soon as you terminate your program others should run normally if they hadn't crashed in the meantime because of the allocation problems.

该内存取自所谓的“堆”。这是您的程序本地的,并在您的程序完成时被完全删除。因此,您的程序对系统和操作系统中运行的其他程序可能造成的“唯一”伤害是它们也可能无法分配内存,因为您的程序已经“吃光”了所有程序。一旦你终止你的程序,其他人应该正常运行,如果他们没有因为分配问题在此期间崩溃。