如果我在一个函数内创建了一个有很多元素的链表,然后在退出函数时没有清理该链表,那么该链表将被创建而没有使用任何malloc调用。
struct list_head {
struct list_head *next, *prev;
}
在退出此函数后,所有资源是否都能得到释放?这样我就可以自由地执行它一百万次,而不会有任何泄漏吗?
主题:如果您没有使用特定的malloc或new调用,则不会发生堆内存泄漏。永远不会。是这样吗?
struct list_head {
struct list_head *next, *prev;
}
在退出此函数后,所有资源是否都能得到释放?这样我就可以自由地执行它一百万次,而不会有任何泄漏吗?
主题:如果您没有使用特定的malloc或new调用,则不会发生堆内存泄漏。永远不会。是这样吗?
泄漏总是和资源相关联。资源的定义是你手动获取的东西,必须手动释放。内存是一个主要的例子,但还有其他资源,如文件句柄、互斥锁、网络连接等。
当你获取资源,但随后丢失了处理该资源的句柄,以至于没有人可以释放它时,就会发生泄漏。泄漏的较小版本是“仍然可访问”的情况,即您不释放资源,但仍然拥有句柄并且可以释放它。这主要是由于懒惰造成的,但泄漏则总是编程错误。
由于您的代码从未获取任何资源,因此也不可能存在任何泄漏。
如果您在没有使用malloc或new的情况下应用变量,则其位于内存中的堆栈空间。因此,当函数返回时,该变量将被收回。
另一方面,您使用malloc或new申请的内存位于堆空间。系统不关心您是否释放了空间。在这种情况下,如果您不使用free或delete,则会发生内存泄漏。
malloc()
从堆上分配内存,而字符串和结构体常量(string1
、string2
以及那些list_head
)的空间将在编译时在堆栈上保留。
实际上,程序所分配的任何内存(堆或栈)都将在进程退出时(至少在*nix系统中)由内核回收。
我会把内存泄漏定义为在堆上分配内存且在程序退出时未释放它。这个定义实际上回答了你的问题。
有一些标准函数(如strdup
)会在堆上分配内存,请注意。
另一个分配后忘记释放的资源示例:
如果你在使用OpenGL,并且调用了glGenBuffers()
一百万次而没有相应的glDeleteBuffers
调用,那么你很有可能会用完VRAM,你的图形驱动程序将开始向系统内存泄漏。
我刚刚遇到了这种情况。幸运的是,Visual Studio的内存分析器让它变得相当容易找到。它显示为外部进程nvoglv32.dll
进行的大量分配。
string2
)赋值,它本来会在堆栈上,但现在你只会得到编译错误。 - Some programmer dudemalloc
或new
分配内存,但不使用free
或delete
释放它。 - Some programmer dudelist_head
不是一个函数(所以它永远不会泄漏),指针通常意味着动态内存分配。你应该问“谁负责释放这个内存和何时释放”。(而问题的答案是:是的。只需使用mmap
即可) - sehe