我最近在CppCon 2016上观看了Herb Sutter关于"Leak Free C++ ..."的精彩演讲,他谈到了使用智能指针实现RAII(资源获取是初始化) - 概念以及它们如何解决大多数内存泄漏问题.
现在我在想.如果我严格遵循RAII规则,这似乎是一件好事,为什么这与C++中的垃圾收集器有什么不同呢?我知道使用RAII,程序员可以完全控制何时再次释放资源,但是在任何情况下都只对垃圾收集器有益吗?它的效率真的会降低吗?我甚至听说有一个垃圾收集器可以更高效,因为它可以一次释放更大的内存块,而不是在代码中释放小内存块.
来自J. Bloch
内存泄漏的来源是监听器......确保回调被及时垃圾回收的最佳方法是仅存储对它们的弱引用,例如,通过仅将它们存储为WeakHashMap中的键 .
那么,为什么Java Collections框架中没有任何WeakSet ?
对于Sun/Oracle的JVM,我读过GC algo将新一代划分为一个Eden区域和两个幸存区域.我想知道的是,为什么两个幸存者地区而不仅仅是一个?算法可以在伊甸园和一个幸存者区域之间保持乒乓(目前两个幸存者区域之间的方式); 或者这种方法有什么缺点吗?
似乎System.Timers.Timer实例通过某种机制保持活跃,但System.Threading.Timer实例却没有.
示例程序,具有定期System.Threading.Timer和自动重置功能System.Timers.Timer:
class Program
{
static void Main(string[] args)
{
var timer1 = new System.Threading.Timer(
_ => Console.WriteLine("Stayin alive (1)..."),
null,
0,
400);
var timer2 = new System.Timers.Timer
{
Interval = 400,
AutoReset = true
};
timer2.Elapsed += (_, __) => Console.WriteLine("Stayin alive (2)...");
timer2.Enabled = true;
System.Threading.Thread.Sleep(2000);
Console.WriteLine("Invoking GC.Collect...");
GC.Collect();
Console.ReadKey();
}
}
Run Code Online (Sandbox Code Playgroud)
当我运行这个程序(.NET 4.0 Client,Release,在调试器之外)时,只有System.Threading.TimerGC是:
Stayin alive (1)...
Stayin alive (1)...
Stayin alive (2)...
Stayin alive (1)...
Stayin …Run Code Online (Sandbox Code Playgroud) 我最近看到两个非常好的和教育性的语言谈话:
Herb Sutter的第一部,介绍了C++ 0x的所有优秀和酷炫功能,为什么C++的未来比以往任何时候都更加明亮,以及M $如何在这场游戏中成为一个好人.该演讲围绕效率展开,如何最大限度地减少堆活动可以提高性能.
这个另一种,安德烈Alexandrescu的,激励一个过渡从C/C++,以他的新的游戏改变d.D的大部分内容似乎都非常有动力和设计.然而,有一件事让我感到惊讶,即D推动垃圾收集,并且所有类都是通过引用创建的.更令人困惑的是,"D编程语言参考手册 "一书特别在关于资源管理的部分中 陈述如下,引用:
垃圾收集消除了C和C++中必需的繁琐,容易出错的内存分配跟踪代码.这不仅意味着更快的开发时间和更低的维护成本,而且最终的程序经常运行得更快!
这与Sutter关于最小化堆活动的不断讨论相冲突.我非常尊重Sutter和Alexandrescou的见解,所以我对这两个关键问题感到有些困惑
不通过引用单独创建类实例会导致很多不必要的堆活动吗?
在哪些情况下我们可以使用垃圾收集而不牺牲运行时性能?
如何将详细垃圾收集输出重定向到文件?Sun的网站显示了Unix的一个例子,但它不适用于Windows.
如果我理解正确,.net运行时将始终在我之后清理.因此,如果我创建新对象并停止在我的代码中引用它们,运行时将清理这些对象并释放它们占用的内存.
既然这就是为什么一些对象需要有一个析构函数或dispose方法呢?当它们不再被引用时,运行时不会清理它们吗?
可能重复:
在JavaScript中删除对象
我有一个具有大量属性的JS对象.如果我想强制浏览器垃圾收集这个对象,我是否需要将每个属性设置为null或者我是否需要使用delete运算符?这两者有什么区别?
执行后我很难理解m1 = null; m2 = null;.有多少个对象可以进行垃圾回收?
public class MyTest {
MyTest m;
void show() {
System.out.println("Hello this is show method.");
}
public static void main(String args[]) {
MyTest m1 = new MyTest();
MyTest m2 = new MyTest();
MyTest m3 = new MyTest();
m1.m = m2;
m2.m = m3;
m3.m = m1;
m1 = null;
m2 = null;
// Question here: How many objects will be eligible for garbage collection?
}
}
Run Code Online (Sandbox Code Playgroud) 我最近与同事讨论了Dispose实施的价值和类型IDisposable.
我认为即使没有非托管资源可以清理IDisposable,也应该尽快清理类型.
我的同事有不同的想法; 执行IDisposable,如果你没有任何非托管资源为你的类型,最终会被垃圾收集是没有必要的.
我的论点是,如果你有一个想要尽快关闭的ADO.NET连接,那么实现IDisposable并且using new MyThingWithAConnection()有意义.我的同事回答说,在封面下,ADO.NET连接是一种非托管资源.我对他回复的答复是,最终所有东西都是一种非托管资源.
我知道推荐的一次性模式,如果Dispose被调用,你可以免费使用托管和非托管资源,但是如果通过终结器/析构函数调用,则只有免费的非托管资源(前面有关于如何提醒消费者不正确使用您的IDisposable类型的博客)
所以,我的问题是,如果你有一个不包含非托管资源的类型,是否值得实现IDisposable?
java ×4
.net ×2
c# ×2
c++ ×2
collections ×1
d ×1
finalization ×1
finalizer ×1
heap-memory ×1
idisposable ×1
javascript ×1
jdk1.5 ×1
jvm ×1
memory ×1
memory-leaks ×1
performance ×1
timer ×1