简体   繁体   English

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

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

We allocate memory in C using malloc and in C++ using new.我们在 C 中使用 malloc 分配内存,在 C++ 中使用 new 分配内存。 I know that memory allocated must be freed or given back to OS using free in C and delete in C++.我知道必须使用 C 中的 free 和 C++ 中的 delete 释放分配的内存或将其返回给操作系统。 If I forgot to use free/delete after allocating memory, it means there will be memory leak.如果我在分配内存后忘记使用 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.我尝试免费,如果我使用 malloc,则删除,新但有时,它会变得混乱。 Is there any tool or method which I can use to know if my program is doing any memory leak ?有什么工具或方法可以让我知道我的程序是否有内存泄漏?

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

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 other processes 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 dynamic or heap allocation.我们在这里讨论的是动态分配或分配。

A memory leak simply means that your application fails 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 guarantee that the OS does that.但是 C/C++ 不保证操作系统会这样做。 It is possible on some platforms that the memory stays lost until you reboot.在某些平台上,内存可能会一直丢失,直到您重新启动。

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 because they know it'll get cleaned up by the OS soon enough.许多短时间运行的程序实际上会忽略内存泄漏,因为它们知道操作系统很快就会清除它。 Microsoft's C++ compiler does this, as far as I know.据我所知,微软的 C++ 编译器就是这样做的。 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 does reclaim memory once the process terminates) So it's ok that it leaks some memory here and there. (他们知道它运行在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::vector uses RAII to manage its resources internally.前者同样有效,但您不必显式调用 delete 来释放它std::vector使用 RAII 在内部管理其资源。 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.你也应该这样做——要么使用现成的 RAII 类,如vectorshared_ptr ,或者标准库或 Boost 中的几乎任何其他类,或者通过编写自己的类。

As a general rule of thumb, your code should not contain any new/delete calls, except in 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。

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 类型系统

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 (eg for gcc, include the -g flag), valgrind will also inform your of the exact line of code where the leaked memory was allocated.如果您的程序是用调试符号编译的(例如,对于 gcc,包括 -g 标志),valgrind 还会通知您分配泄漏内存的确切代码行。 This will greatly ease the task of tracking and fixing leaks.这将大大简化跟踪和修复泄漏的任务。

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.使用 valgrind 的好处是它不仅仅检查内存泄漏。 See http://valgrind.org/info/tools.htmlhttp://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(和夹板),这已被证明是无价的!

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

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

There is a programming idea called Resource Acquisition Is Initialization ( RAII ).有一种编程思想叫做资源获取即初始化( 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."这意味着“如果您需要分配需要删除的内存,或者确保您打开的东西被关闭,请将其包装在您在堆栈上创建的对象中。这样当对象超出析构函数的范围时自动被调用,然后您在析构函数中删除您的资源。”

Common memory leaks happen when you write a "new" in the code, but your function exits before you call delete.当您在代码中编写“new”时会发生常见的内存泄漏,但您的函数在调用 delete 之前退出。 Sometimes you encounter a "return" statement too early, other times an exception gets thrown and caught after your "delete" statement.有时您会过早地遇到“return”语句,有时会在“delete”语句之后抛出并捕获异常。 Following RAII helps you make sure those accidents don't happen.遵循 RAII 可帮助您确保不会发生这些事故。

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.用户需要定期重新启动应用程序以避免这种情况发生或使用过多的系统资源。

Update 1:更新 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.它不是一个理想的情况。

Update 2:更新 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.但是应该防止内存泄漏仅仅因为它们是一个错误,并且您永远不应该以错误是可以接受的观点编写代码。

Update 3:更新 3:
The best way to prevent memory leaks is not to use malloc/free in the first place.防止内存泄漏的最佳方法是首先不要使用 malloc/free。 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.如果您在 RAII 上使用 C++ 阅读,使用类并复制对象,这将确保您永远不会有泄漏......几乎所有时间。 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.永远不要将内存分配给您可能会忘记的局部变量,可能会从函数返回而不通过 free 调用,可能会传递给另一个没有被调用的函数以释放。 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).为此需要一种纪律感(不需要太多纪律),但很多人会告诉你,无论如何编写好的、正确的、设计良好的、无错误的代码也需要同样的美德(他们是对的 -如果您曾经见过与精心设计的代码相比的黑客代码,您将能够立即看到差异)。

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.在 GC 语言中这样做是很常见的,因为人们认为 GC 会为他们做所有的工作。 Again, coding/design discipline is required - know what you're doing will prevent these bugs.同样,编码/设计纪律是必需的——知道你在做什么可以防止这些错误。

Memory leaks can occur even without using malloc/new.即使不使用 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.我有史以来最大的泄漏源是使用 MSXML,我创建了一个 XML 对象的 CComPtr,然后调用该方法来获取一个元素,将该对象作为参数传递给该方法。 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.这里的寓意是,如果使用智能指针类,请确保您知道它在做什么,尤其是它的强制转换运算符。

Tools:工具:
you don't need to buy Purify if running on Windows.如果在 Windows 上运行,则无需购买 Purify。 Microsoft offers UMDH which takes snapshots of your memory. Microsoft 提供了UMDH ,它可以对您的内存进行快照。 Take 2 snapshots and compare them using the tool, and you can see allocations that steadily increase over time without being de-allocated.拍摄 2 个快照并使用该工具进行比较,您可以看到分配随着时间的推移稳步增加而不会被取消分配。 Its not pretty, but it works.它不漂亮,但它有效。

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

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.一旦你终止你的程序,其他人应该正常运行,如果他们没有因为分配问题在此期间崩溃。

A tool for monitoring memory leaks is to override the new and delete operators.监控内存泄漏的一个工具是覆盖 new 和 delete 操作符。 This allows you to maintain a list of memory that has been allocated and not freed.这允许您维护已分配和未释放的内存列表。 So, if a particular object should have freed all of the memory it is using, this mechanism gives you a way to verify that it really has freed the memory.因此,如果某个特定对象应该释放它正在使用的所有内存,则此机制为您提供了一种验证它是否真的释放了内存的方法。

Along with Purify, you might try a free alternative: valgrind.除了 Purify,您还可以尝试一个免费的替代方案:valgrind。 The stipulation there is that valgrind is a linux-specific solution.那里的规定是 valgrind 是特定于 linux 的解决方案。

To answer update 3 there is usually a way to indicate whether your process has any outstanding memory allocations _heapwalk (under Win32) will allow you to step through all your allocations and you can see if there are any outstanding.要回答更新 3,通常有一种方法可以指示您的进程是否有任何未完成的内存分配 _heapwalk(在 Win32 下)将允许您逐步完成所有分配,您可以查看是否有任何未完成的分配。

Beyond that its probably worth wrapping your malloc/new calls so that you record the file and line number of each allocation when it happens.除此之外,它可能值得包装您的 malloc/new 调用,以便您在它发生时记录每个分配的文件和行号。 Then in your overridden delete/free you remove it from the list.然后在覆盖的删除/释放中将其从列表中删除。

eg (Be warned this is totally untested code so it probably won't work off the bat)例如(请注意,这是完全未经测试的代码,因此可能无法立即使用)

struct MemoryAllocEntry
{
    char* pFile;
    char* pLine;
};

extern std::map< MemoryAllocEntry > g_AllocList;

inline void* MyMemAlloc( size_t size, char* pFile, char* pLine )
{
    MemoryAllocEntry mae;
    void* pRet = malloc( size );
    mae.pFile = pFile;
    mae.pLine = pLine;

    g_AllocList[pRet] = mae;

    return pRet;
}

inline void MyMemFree( void* pPtr )
{
    std::map< MemoryAllocEntry >::iterator iter = g_AllocList.find( pPtr );
    if ( iter != g_AllocList.end() )
    {
         g_AllocList.erase( iter );
    }
    free( pPtr );
}

#ifdef _DEBUG
    #define malloc( x ) MyMemAlloc( (x), __FILE__, __LINE__ )
    #define free( x ) MyMemFree( (x) )
#endif

Then all you need to do is step through g_AllocList to find any outstanding allocations.然后您需要做的就是单步执行 g_AllocList 以查找任何未完成的分配。 The above obviously only works for malloc and free but you can make it work for new and delete as well (MFC does it, for example).以上显然仅适用于 malloc 和 free 但您也可以使其适用于 new 和 delete (例如,MFC 可以做到)。

In answer to your question, and update 1,:回答您的问题,并更新1:

Not all operating systems support the notion of distinct processes, hence will never automatically clean things up.并非所有操作系统都支持不同进程的概念,因此永远不会自动清理。

For example, an embedded OS like VxWorks (in some configurations) does not support the concept of multiple processes, so even after your task has ended, any memory you failed to deallocate will remain.例如,像 VxWorks 这样的嵌入式操作系统(在某些配置中)不支持多进程的概念,因此即使在您的任务结束后,您未能释放的任何内存仍将保留。 If that wasn't intended, you will end up with a memory leak.如果这不是故意的,您最终会出现内存泄漏。

Moreover, such a platform is probably used on a system which is rarely rebooted and doesn't support swap, so any memory leaks are much more serious than they would be on (for example) a desktop.此外,这样的平台可能用在很少重新启动且不支持交换的系统上,因此任何内存泄漏都比(例如)台式机上的内存泄漏严重得多。

The correct way to avoid memory leaks is to do less explicit memory management and rely on containers which manage stuff for you, for example STL in C++ (relevant parts of it).避免内存泄漏的正确方法是不那么显式地进行内存管理,并依赖于为您管理内容的容器,例如 C++ 中的 STL(它的相关部分)。

Low-level embedded programmers using C often avoid memory leaks by statically allocating everything at startup.使用 C 的低级嵌入式程序员通常通过在启动时静态分配所有内容来避免内存泄漏。 C programmers can also use stack allocation with alloca() to avoid possible memory leaks (but they need to understand exactly how it works). C 程序员还可以使用 alloca() 的堆栈分配来避免可能的内存泄漏(但他们需要准确了解它是如何工作的)。

It's the memory assigned to the proccess.这是分配给进程的内存。 You will get it back when you kill the proccess.当你杀死进程时,你会得到它。

Memory leaks typically cause problems for long running programmes;内存泄漏通常会导致长时间运行的程序出现问题; leaks of just a few bytes in unfortunate places such as loops can rapidly expand the memory footprint of your application.在不幸的地方(例如循环)中仅仅几个字节的泄漏会迅速扩大应用程序的内存占用。

Answering the edit -回答编辑 -

If your program is meant to run,.如果您的程序要运行,. so something and then terminate then no you don't need to be too worried about freeing memory.所以有些东西然后终止然后不你不需要太担心释放内存。 It's important for programs that run for a while.这对于运行一段时间的程序很重要。 If your web browser didn't free memory it used to display a page, it would soon use all the memory in your computer.如果您的网络浏览器没有释放用于显示页面的内存,它很快就会使用您计算机中的所有内存。

it's good practice to free memory anyway though, small programs that run once have a habit of being turned into other things and it's a good habit to get into.无论如何,释放内存是一个好习惯,运行一次的小程序有一个习惯,它会变成其他东西,这是一个好习惯。

当程序在 Windows 中完成时,它不仅释放内存,而且释放所有句柄(如果我错了,请纠正我)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM