我没有编程很长时间,并且是C / C ++的新手。我过去总是使用C#,但我已经切换到本机代码来编写我的第一个Win32 API应用程序。我从C开始,但在没有上课的情况下努力工作变得越来越疯狂。
我已经开始将一些C移植到C ++。最初,我使用.NET 4将项目设置为VC ++。大约25%的移植方式,我在调试模式下运行程序。我感到震惊。根据任务管理器,该程序使用的内存量是C版本的两倍多。然后,我对该项目进行了de-.NET化,并且更加惊讶:仅使用STL,我的应用程序需要33%的.NET内容所需的内存。以下是数字:
内存使用
完整的应用程序在C:............... 940kb
VC ++ /。NET4中25%的端口:...... 2.1MB
C ++中25%的端口:................... 700kb
如果我把.NET的其他功能放在一边,我想知道如果内存占用量增加三倍,托管内存的优势是什么。它是泄漏的先发制人吗?更安全的指针?
由于
答案 0 :(得分:3)
您看到的部分内存占用也将属于.Net Framework的运行时。
垃圾收集有助于消除大量编程开销,例如记住dealloc内存或释放对象。我已经在C,Objective C和C#中编写了很多程序,我当然可以说虽然垃圾收集并不能解决所有问题,但它确实消除了我的很多责任,并且让我专注于逻辑而不是寻找exra释放说明。
我还认为新对象的分配机制非常快,因为它总是会添加到内存地址的末尾,而不是必须搜索足够大的块。
我应该说虽然垃圾收集很好,但它并不完美,并且在.Net中有自己的限制,特别是在处理非托管代码时,即不调用dispose可能会留下内存延迟到最终确定。收集周期也可能很昂贵,因为所有活动在垃圾收集期间都会暂停。
与任何技术一样,了解其优点和缺陷并进行适当选择。
答案 1 :(得分:3)
Everyone thinks about garbage collection the wrong way。除非系统存在内存压力,否则CLR几乎没有理由一直执行垃圾收集传递。所以它不会这样做。这并不意味着内存被有效泄露,只是垃圾收集器还没有完全清除它。
一般来说,根据当前使用的内存量对任何垃圾收集语言进行基准测试并不是一个有意义的比较,因为它完全取决于垃圾收集器的行为,这既不是确定性的也不在你的控制之下。
答案 2 :(得分:2)
垃圾收集,我想没有悬空参考。和反思。
答案 3 :(得分:1)
您是否在查看任务管理器中的内存使用情况?这不是分析您的应用的准确方法:该数字中会捆绑大量不相关的数据。
对于托管应用程序,我希望看到由于加载运行时而导致增加。此外,.NET垃圾收集器并不积极回收内存:它试图延迟收集,直到它将耗尽内存。
垃圾收集的应用程序倾向于比非托管应用程序更好地分配内存。非托管内存容易碎片化:某些分配模式会在整个内存中留下漏洞,虽然新分配的总可用内存足够多,但新分配可能比最大漏洞大。
垃圾回收器通过每次执行分配时压缩内存来避免碎片:它在内存中将对象移动到彼此旁边,在末尾留下一个大洞。由于这个原因,后续分配可以很快:托管内存分配器不需要查看漏洞列表,但可以直接到堆的末尾。 [1]
除非您分配大量内存,否则不要担心内存使用情况。
[1]这不适用于用于大对象的堆(大于约85KB)。大对象堆的工作方式类似于常规malloc
/ free
堆。
答案 4 :(得分:0)
我也是DotNet编程的新手,但我已经做了很长时间的C / C ++编程。根据我的理解,如果您担心内存使用,则不要使用DotNet。任何具有Java或C#等中间层的平台都将具有更高的内存使用率。与其他人解释的普通c / C ++编程相比,权衡不仅仅是垃圾收集和内存管理,还有更丰富的库。如果没有DotNet我必须做我现在正在做的事情,我会花费至少三倍的时间。不要记住更多错误并处理它们。 还有一个垃圾收集器,它可以在不需要占用CPU时间的情况下清除内存,而CPU时间本来可以分配给您的进程,并使您的进程等待。所以额外的内存开销实际上并不是一件坏事。
答案 5 :(得分:0)
你的内存占用空间很小我认为这可能解释了你的反直觉结果。两个系统都有开销。他们使用大约1 GB的内存运行类似的测试,你应该看到你认为会发生什么。