Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/csharp-4.0/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 4.0 使用GC和LOH正确识别内存泄漏_C# 4.0_Memory Management_Garbage Collection - Fatal编程技术网

C# 4.0 使用GC和LOH正确识别内存泄漏

C# 4.0 使用GC和LOH正确识别内存泄漏,c#-4.0,memory-management,garbage-collection,C# 4.0,Memory Management,Garbage Collection,这可能会被问到一些不同的方式,但这对我来说是一个相对较新的领域,所以请原谅我,如果它是多余的,并指出我的道路 基本上,我已经创建了一个数据收集引擎,它以每秒数千点的速度收集数据,并将其存储在数据库中 数据库是动态的,因此输入到数据库的语句也是在代码中动态创建的,这反过来又需要大量的字符串操作。但是,所有字符串都是在异步事件处理程序方法的作用域内声明的,因此它们应该在方法完成后立即脱离作用域 当这个应用程序运行时,根据TaskManager/process explorer,它的内存使用率会缓慢但

这可能会被问到一些不同的方式,但这对我来说是一个相对较新的领域,所以请原谅我,如果它是多余的,并指出我的道路

基本上,我已经创建了一个数据收集引擎,它以每秒数千点的速度收集数据,并将其存储在数据库中

数据库是动态的,因此输入到数据库的语句也是在代码中动态创建的,这反过来又需要大量的字符串操作。但是,所有字符串都是在异步事件处理程序方法的作用域内声明的,因此它们应该在方法完成后立即脱离作用域

当这个应用程序运行时,根据TaskManager/process explorer,它的内存使用率会缓慢但稳定地增加,因此似乎有些东西没有得到正确的处理和/或收集

如果我附加CDB-p是,我将从CLR加载sos.dll并执行一个!dumpheap我看到System.String正在使用其中的大部分,如果我是!dumpheap-type System.String和!我看到的地址与SQL语句中的字符串完全相同

但是如果我做了一个!gcroot在任何一个地址上,我发现0个唯一的根运行'!GCRoot-all'查看所有根。反过来,如果我按照它所暗示的那样尝试,我会得到无效的论点——都是O.O

所以在谷歌搜索了一番之后,以及一些关于无根对象最终将由GC收集的争论之后,这不是一个问题。。我看了看,我的问题似乎有84%是在LOH上,根据你看的线程的不同,可能会或可能不会被GC处理,除非机器上有内存限制,或者我明确告诉它收集根据我能找到的所有东西认为是坏的

所以我需要知道的是,这本质上是真的,这不是内存泄漏,这只是系统在回收之前留下的东西,如果是这样,那么我如何判断我是否有合法的内存泄漏

这是我第一次在应用程序外部使用调试器,因为我以前从未解决过此类问题,所以我对这一部分非常陌生,这是一次学习经验


应用程序是用VS2012 Pro,C编写的,它是多线程的,一个控制台应用程序正在包装API进行测试,但最终将成为一个Windows服务。

您读到的是真的,托管应用程序使用一种内存模型,在该模型中,对象不断堆积,直到达到某个内存阈值,该阈值是根据系统上的物理内存量和应用程序的实际增长率计算得出的,在此之后,所有*死掉的对象都会被剩余的有用内存压扁,从而使其成为一个连续的块以提高分配速度

所以,是的,不要担心你的内存会稳步增加,直到你的内存增加了几十MB,并且没有进行任何收集


*-由于基于对象大小和生命周期长度的多个内存池,使得系统不会不断地探测非常长寿命的对象,并且由终结器进行探测,因此实际上更为复杂。当一个对象有一个终结器时,内存不是被释放,而是被挤压到它们上面,但它们被移动到一个特殊的队列,终结器队列,在那里它们等待终结器在UI线程上运行。请记住GC在一个单独的线程上运行,然后它才最终被释放。

不过,请注意,所有这些并不是说泄漏是不可能的。事实上,如果你不小心的话,咖喱可以增加很多方法来泄漏句柄。有没有比任何方法更能检查事实呢?事实确实如此。在我的开发机器32GB的ram上几乎没有内存限制,我做了很多并发虚拟机来测试最终环境将是理论上可以运行很长时间的机器,我不希望人们回来获取数据以发现一个月前内存不足的异常关闭它。。Id est,那么您如何真正跟踪内存泄漏?或者什么是公认的足够好的标准看看你的对象和它们是如何使用的,看看你的curry函数和事件处理程序,不难避免像C这样的托管语言中的漏洞。如果你想直观地看到它,我推荐JetBrains的dotMemory,我想他们有一个试用版。从长远来看,在第一个小时的运行中,我看到了一个大约15米的足迹,到两天结束时,它已经增长到75米,终端机器可能是2gb运行w7,它们是小型工业机器,按照这个速度,如果我在这个问题上错了,理论上我可以在几周或更短的时间内填满它们。是的,按照这个速度,你会变老,在看到GC之前就会死去。如果你真的很好奇的话,放一个GC.Collect按钮,你会在那个时间点看到零点。如果每隔5分钟单击一次,您将看到类似的值。但不要在生产代码中使用它,这只是为了了解在没有侵入性工具和内存的情况下会发生什么