分析、调试内存泄漏的应用程序

<!-- /* Font Definitions */ @font-face {font-family:Wingdings; panose-1:5 0 0 0 0 0 0 0 0 0; mso-font-charset:2; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:0 268435456 0 0 -2147483648 0;} @font-face {font-family:宋体; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-alt:SimSun; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} @font-face {font-family:"Cambria Math"; panose-1:2 4 5 3 5 4 6 3 2 4; mso-font-charset:0; mso-generic-font-family:roman; mso-font-pitch:variable; mso-font-signature:-1610611985 1107304683 0 0 159 0;} @font-face {font-family:Calibri; panose-1:2 15 5 2 2 2 4 3 2 4; mso-font-charset:0; mso-generic-font-family:swiss; mso-font-pitch:variable; mso-font-signature:-1610611985 1073750139 0 0 159 0;} @font-face {font-family:"/@宋体"; panose-1:2 1 6 0 3 1 1 1 1 1; mso-font-charset:134; mso-generic-font-family:auto; mso-font-pitch:variable; mso-font-signature:3 135135232 16 0 262145 0;} /* Style Definitions */ p.MsoNormal, li.MsoNormal, div.MsoNormal {mso-style-unhide:no; mso-style-qformat:yes; mso-style-parent:""; margin:0cm; margin-bottom:.0001pt; text-align:justify; text-justify:inter-ideograph; mso-pagination:none; font-size:10.5pt; mso-bidi-font-size:11.0pt; font-family:"Calibri","sans-serif"; mso-ascii-font-family:Calibri; mso-ascii-theme-font:minor-latin; mso-fareast-font-family:宋体; mso-fareast-theme-font:minor-fareast; mso-hansi-font-family:Calibri; mso-hansi-theme-font:minor-latin; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi; mso-font-kerning:1.0pt;} .MsoChpDefault {mso-style-type:export-only; mso-default-props:yes; mso-bidi-font-family:"Times New Roman"; mso-bidi-theme-font:minor-bidi;} /* Page Definitions */ @page {mso-page-border-surround-header:no; mso-page-border-surround-footer:no;} @page Section1 {size:595.3pt 841.9pt; margin:72.0pt 90.0pt 72.0pt 90.0pt; mso-header-margin:42.55pt; mso-footer-margin:49.6pt; mso-paper-source:0; layout-grid:15.6pt;} div.Section1 {page:Section1;} /* List Definitions */ @list l0 {mso-list-id:1745568359; mso-list-template-ids:1176537200;} @list l0:level1 {mso-level-number-format:bullet; mso-level-text:; mso-level-tab-stop:36.0pt; mso-level-number-position:left; text-indent:-18.0pt; mso-ansi-font-size:10.0pt; font-family:Symbol;} ol {margin-bottom:0cm;} ul {margin-bottom:0cm;} --> 项目组的一个window service (7×24)出现 OutOfMemory异常,一直找不到原因。尝试过各种方法。

1、去掉方法和类中 static ,以便资源释放;

2、将无线等待的“死”循环while(true){...} 更改为 心跳触发;

3、将核心类实现 IDisposiable 接口,以便更好释放资源;

等等,其他很多优化的操作,均不见效。这个问题也成为项目组的一个心病。

一个偶然的机会,在对比服务器800M 和900M的.dmp文件时,无意间看到 !dumpdomain -stat 中,AppDomain的Assembly 居然有1800、2000个(My God),为啥这里会出现这么多的Assembly。

经 过咨询项目老大后才知道,项目中有一个动态编译c#的模块,编译时会生成内存中的Assembly,而默认情况下,这个Assembly是直接加载在 AppDomain中,除非 AppDomain卸载,否则Assembly会一直随着应用程序域的存在而持续存在,虽然这个过程仅占用0.6Kbytes的内存,但是对于 7*24小时的服务来说,OutOfMemory只是时间的问题而已。剩下的就是想办法如何解决这个问题了。

 

ps:贴一篇MS的文章,在这里终于找到了佐证。

 

原文:http://msdn.microsoft.com/zh-cn/magazine/cc163491.aspx

 

调试内存泄漏的应用程序

发现并防止托管代码中出现内存泄漏

James Kovacs

 

本文讨论:

  • 理解托管应用程序中的内存泄漏问题
  • .NET 应用程序中所用的非托管内存
  • 帮助 .NET 垃圾收集器发挥应有功效

本文使用了以下技术:
.NET Framework

下载本文中所用的代码: MemoryLeaks2007_01.exe (163 KB)
浏览在线代码

http://i.msdn.microsoft.com/Global/Images/clear.gif  目录

.NET 应用程序中的内存
检测泄漏
堆栈内存泄漏
非托管堆内存泄漏
泄漏”托管堆内存
总结

一提到托管代码中出现内存泄漏,很多开发人员的第一反应都认为这是不可能的。毕竟垃圾收集器 (GC) 会负责管理所有的内存,没错吧?但要知道,垃圾收集器只处理托管内存。基于 Microsoft® .NET Framework 的应用程序中大量使用了非托管内存,这些非托管内存既可以被公共语言运行库 (CLR) 使用,也可以在与非托管代码进行互操作时被程序员显式使用。在某些情况下,垃圾管理器似乎在逃避自己的职责,没有对托管内存进行有效处理。这通常是由于不 易察觉的(也可能是非常明显的)编程错误妨碍了垃圾收集器的正常工作而造成的。作为经常与内存打交道的程序员,我们仍需要检查自己的应用程序,确保它们不 会发生内存泄漏并能够合理有效地使用所需内存。

 

.NET 应用程序中的内存

您大概已经知道,.NET 应用程序中要使用多种类型的内存,包括:堆栈、非托管堆和托管堆。这里我们需要简单回顾一下。

堆栈 堆栈用于存储应用程序执行过程中的局部变量、方法参数、返回值和其他临时值。堆栈按照每个线程进行分配,并作为每个线程完成其工作的一个暂存区。垃圾收集 器并不负责清理堆栈,因为为方法调用预留的堆栈会在方法返回时被自动清理。但是请注意,垃圾收集器知道在堆栈上存储的对象的引用。当对象在一种方法中被实 例化时,该对象的引用(32 位或 64 位整型值,取决于平台类型)将保留在堆栈中,而对象自身却存储于托管堆中,并在变量超出范围时被垃圾收集器收集。

非托管堆 非托管堆用于运行时数据结构、方法表、Microsoft 中间语言 (MSIL)JITed 代码等。非托管代码根据对象的实例化方式将其分配在非托管堆或堆栈上。托管代码可通过调用非托管的 Win32® API 或实例化 COM 对象来直接分配非托管堆内存。CLR 出于自身的数据结构和代码原因广泛地使用非托管堆。

托管堆 托管堆是用于分配托管对象的区域,同时也是垃圾收集器的域。CLR 使用分代压缩垃圾收集器。垃圾收集器之所以称为分代式,是由于它将垃圾收集后保留下来的对象按生存时间进行划分,这样做有助于提高性能。所有版本的 .NET Framework 都采用三代分代方法:第 0 代、第 1 代和第 2 代(从年轻代到年老代)。垃圾收集器之所以称为压缩式,是因为它将对象重新定位于托管堆上,从而能够消除漏洞并保持可用内存的连续性。移动大型对象的开销 很高,因此垃圾收集器将这些大型对象分配在独立的且不会压缩的大型对象堆上。有关托管堆和垃圾收集器的详细信息,请参阅 Jeffrey Richter 所著的分为两部分的系列文章垃圾收集器:Microsoft .NET Framework 中的自动内存管理垃圾收集器 第 2 部分:Microsoft .NET Framework 中的自动内存管理。虽然该文的写作是基于 .NET Framework 1.0,而且 .NET 垃圾收集器已经有所改进,但是其中的核心思想与 1.1 版或 2.0 版是保持一致的。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Linux系统中,应用内存分析内存分析是两个不同的任务。 应用内存分析主要是通过查看应用程序内存使用情况,找出应用程序中存在的内存泄漏内存溢出等问题,以优化应用程序的性能。可以使用工具如valgrind、gdb等。 内存分析则是对整个系统的内存使用情况进行分析,找出哪些进程或应用程序占用了过多的内存,从而优化系统的性能。可以使用工具如top、ps、free、vmstat、sar等。 下面简单介绍一些工具的使用方法: 1. valgrind:是一个开源的内存调试和性能分析工具,可以检测应用程序中的内存泄漏、越界访问、使用未初始化的内存等问题。使用方法:valgrind [options] your_program 2. gdb:是一个强大的调试器,可以用来调试C、C++等程序。使用方法:gdb your_program,然后输入命令run启动程序,再输入命令break设置断点,用命令print查看变量的值。 3. top:是Linux系统中常用的进程监控工具,可以实时查看系统的进程和资源使用情况。使用方法:在终端中输入top命令即可。 4. ps:也是Linux系统中常用的进程查看工具,可以查看进程的PID、进程名、进程状态等信息。使用方法:在终端中输入ps命令即可。 5. free:可以查看系统的内存使用情况。使用方法:在终端中输入free命令即可。 6. vmstat:可以查看系统的虚拟内存使用情况。使用方法:在终端中输入vmstat命令即可。 7. sar:可以查看系统的CPU、内存、磁盘等资源使用情况。使用方法:在终端中输入sar命令即可。 以上是一些常用的Linux应用内存分析内存分析工具,使用这些工具可以更好地了解系统和应用程序内存使用情况,从而进行优化和改进。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值