是否有可能在.NET中的堆栈中发生内存泄漏?

Fir*_*roz 5 .net c# memory-leaks

内存泄漏是,当应用程序中有未使用的内存且GC可以收集它时,通常会发生在应用程序中的某些地方我们保留不需要的对象的强引用,并且GC将能够找到路径(直接和间接)以便它可以释放这个对象,但是这一切都适用于堆内存分配中的引用类型.

但是堆栈呢?据我所知,GC不负责清理堆栈,当函数返回时它会自动清理.

所以我的问题是,是否有可能在堆栈中发生内存泄漏?如果是,那么在什么情况下以及避免这种泄漏的最佳做法是什么.

Bri*_*ian 2

如果您编写的递归函数保留对子递归调用中不需要的大数据的堆栈本地引用,那么这是一种空间泄漏,但在实践中这种问题很少见。

更一般地说,如果你有类似的东西

Main() {
    var s = ReadInAGiganticString();   // say 10 Megs long
    Server(s.Substring(0,5));          // but I only care about first 5 chars
}
Server(s) {
    while(true) { ... }                // but 10M is on stack forever
}
Run Code Online (Sandbox Code Playgroud)

那么这是一种堆栈空间泄漏,但同样,在实践中不太可能。修复方法很简单:

Main() {
    var s = ReadInAGiganticString();
    var t = s.Substring(0,5);
    s = null;                         // the fix
    Server(t);
}
Server(s) {
    while(true) { ... }
}
Run Code Online (Sandbox Code Playgroud)

一般来说,如果在调用之前堆栈上有一个巨大的变量,该变量将持续“很长一段时间”并且不再使用该变量,则可以将其清空以确保在进入之前可以对其进行 GC。 “长”电话。

(优化器可能会根据可达性分析为您执行此操作。)

请注意,上面的答案适用于对以堆栈为根的堆分配对象的引用。另一方面,如果您有堆栈分配的内存(例如巨大的结构或 stackalloc 事物),那么修复并不那么容易,但在实践中这种情况更加罕见(谁创建过巨大的结构?)。

  • 只有对字符串的引用位于堆栈上,字符串本身驻留在堆上。 (2认同)