分享.net常见的内存泄露及解决方法(转)

NET程序内存泄漏处理技巧/调试内存泄漏教程 使用Visual Studio分析.NET Dump,快速查找程序内存泄漏问题 阅读详情

转自:http://developer.51cto.com/art/201106/269461.htm

 

关于内存泄漏的问题,之前也为大家介绍过,比如:检测C++中的内存泄漏,是关于C++内存泄漏的。今天为大家介绍的是关于.NET内存泄漏的问题。

前段时间帮项目组内做了一次内存优化,产品是使用c#开发的winForm程序,一直以为.net提供了垃圾收集机制,开发的时候也没怎么注意内存的释放,导致最后的产品做出来之后,运行一个多小时就内存直接崩溃了,看来.net的垃圾收集还是得需要开发者加以控制,也不是万能的啊。

下面将对垃圾收集做以简介,然后描述一下我在内存优化过程中常见的内存泄露及解决方法。

托管堆的内存分配(下文中的托管堆指的是GC堆)

托管堆是以应用程序域为依托的,即每一个应用程序域有一个托管堆,每一个托管堆也只属于一个应用程序域,且托管堆是一块连续的内存,其中的对象也是紧密排列的。相对于C++中的非连续内存堆来说,托管堆的内存分配效率要高。托管堆维护了一个指针,指向当前已使用内存的末尾,当需要分配内存的时候,只需要指针向后移动指定数量的位置即可。而且托管堆通过应用程序域实现了应用程序之间内存的隔离,即不同的应用程序域之间在正常情况下是不能相互访问各自的托管堆的。

垃圾收集

垃圾收集的算法有很多。例如引用计数、标记清除等等,托管堆使用的标记清除算法。

托管堆使用的是分代标记清除算法。

标记清除算法

首先,系统将托管堆内所有的对象视为可以回收的垃圾,然后系统从GCRoot开始遍历托管堆内所有的对象,将遍历到的对象标记为可达对象,在遍历完成之后,回收所有的非可达对象,完成一遍垃圾收集。

注意,托管堆的垃圾收集只会自己收集托管对象!

由于在执行完垃圾收集之后,托管堆中会产生很多的内存碎片,导致内存不再连续,因此在垃圾收集完成之后,系统会执行一次内存压缩,将不连续的内存重新排列整齐,变成连续的内存。(关于垃圾收集的详细信息,大家可以参考《CLR Via C#》)

通过上面的简述,大家都知道什么样的对象不会被收集,即能从GCRoot开始遍历到的对象。

最常见的GCRoot是线程的栈,线程的栈里面通常包含方法的参数、临时变量等。另外常见的GCRoot还有静态字段、CPU寄存器以及LOH堆上的大的集合。因此,如果想要让托管对象的内存顺利的释放,只需要断开与跟之间的联系即可。而对于非托管对象的内存,必须进行手动释放。

下面我根据自己在优化内存的过场中的一些常见错误以及一些解决方法。

事件

在.net内存泄露的原因当中,事件占据了非常大的一部分比例,事件是一种委托的实例,也就是与我们类中其他的字段一样,也是一个字段。

委托为什么能阻止垃圾收集呢?即委托是如何让相关的对象在垃圾收集的时候被标记为可达对象的呢?首先要从委托的本质看起,

我们通常使用的委托是从类

 
  1. public abstract class MulticastDelegate : Delegate 

继承的,MulticastDelegate内部维护了一个private object _invocationList;,即我们通常所有的委托链(ps:委托链同字符串一样,是不可变的),这个委托链是以个object [],内部保存了Delegate对象,及每一个委托实际上是一个Delegate对象,而Delegate包含了两个非常重要的字段:

 
  1. internal object _target;  
  2. internal object _methodBase; 

其中_target就是订阅事件的对象,_methodBase则是订阅事件的方法的 MethodInfo。其关联关系如下例所示:

 
  1. Code:  
  2. public event EventHandler TestEvent;  
  3. void MethodEndTempVarClear()  
  4. {  
  5. Test tempTestEvent = new Test();  
  6. TestEvent += tempTestEvent.TestEvent;  
  7. } 

我们假设此段代码所在的对象即为一个可达的对象,则其引用关系如下图所示:

引用关系图 

由上图我们可以看出,原本应该在方法结束后就可以变为不可达对象的tempTestEvent变成了可达对象,因此也不能对其进行收集了。

个人建议:将类中所有的事件订阅添加到一个专门的方法当中,且实现一个与其匹配的取消订阅的方法,并在必要的时候,调用取消订阅的方法。

非托管对象

非托管对象无论在什么时候,都不会被垃圾收集所回收,必须手动释放。

.net中的非托管资源都实现了IDispose接口,我们可以在使用的时候,使用using(){}类实现非托管资源的释放。

其中有一种情况非常容易遗漏,即通过一个方法创建了一个非托管的对象,如下所示:

 
  1. public MemoryStream CreateAStream()  
  2. {  
  3. return new MemoryStream();  
  4. } 

大家在使用的时候非常容易遗忘通过这种方法的形式创建的非托管对象,尤其是一些名字意义表达不准确的时候,例如

 
  1. var temp = CreateATemp();//CreateATemp返回一个非托管对象 

大家可能会漏掉对temp的内存释放,因此建议大家尽量少用方法创建或者初始化非托管对象,如果需要,则使用如下的方式:

 
  1. bool InitializeStream(out MemoryStream stream)  
  2. {  
  3. stream = new MemoryStream();  
  4. return true;  
  5. } 

即使用out关键字,这样大家在使用这个方法的时候,需要首先声明相关的非托管对象,可以在使用完成之后,及时的释放,减少遗漏。

集合/静态字段

对于集合,我们在使用完成之后,需要即时的clear,尤其是将一些方法中的临时变量添加到集合当中之后,会导致集合膨胀,并使得其中的内存泄露。

对于静态字段,我们应该尽量减少其可见的域,因为静态字段在整个程序运行期间都不会被释放,减少其可见域就减少了其内存泄露的可能性,注意,不到万不得以,千万不要声明静态的集合,就是使用了,那也一定要小心再小心。静态集合很容易造成内存泄露。

关于MFC中CString内存泄露的问题 <!-- alimama_pid="mm_10249644_1605763_4929893"; alimama_titlecolor="707070"; alimama_descolor ="CCCCCC"; alimama_bgcolor="FFFFFF"; alimama_bordercolor="FFFFFF"; alimama_linkcolor="DADA 阅读详情

相关推荐

NWD 格式转换 STL 全流程:专业方案与迪威模型网在线转换详解

在3D模型处理中,将NWD文件转换为STL格式是常见的需求,特别是在3D打印和计算机辅助制造等领域。NWD文件由Autodesk开发,主要用于建筑、工程和施工行业,包含丰富的几何图形和材质信息,但因其专有格式和大文件大小,限制了其应用范围。相比之下,STL格式广泛应用于3D打印,仅包含表面几何信息。转换NWD到STL的原因包括拓展模型应用场景和便于模型编辑。转换方法包括使用专业软件如Autodesk Navisworks配合Blender或3ds Max,或使用专门的转换工具如CADExchanger。

技术说明博主 2540

.net常见的内存泄露及解决方法

前段时间帮项目组内做了一次内存优化,产品是使用c#开发的winForm程序,一直以为.net提供了垃圾收集机制,开发的时候也没怎么注意内存的释放,导致最后的产品做出来之后,运行一个多小时就内存直接崩溃了,看来.net的垃圾收集还是得需要开发者加以控制,也不是万能的啊。 本人第一次写博客,可能知识储备不足,会有错误,但是我不怕有错误,就怕大家不指出,呵呵,希望大家及时指正,共同进步。 下面将对垃...

weixin_34393428的博客 390

如何构建高质量的 QA 问答知识库

NLP 技术落地最普遍的场景就是智能客服,如阿里的”小蜜“,京东的“JIMI”等等。NLP 技术也广泛应用于搜索系统。无论是“智能客服”,还是“搜索系统”,构建的前提是拥有“高质量的QA知识库”。今天聊聊“如何构建高质量QA知识库。”。 历史对话数据分布分析 基于公司现有系统积累的大规模对话文本数据,需要对文本数据进行归类处理,分析每个部分数据的占比,挖掘出有价值的文本通过 NLP 相关技术进行商业价值转化。下文以医疗领域来举例说明,通过输入对象,可以将文本分为客服输入和用户输入两部分。挖掘相关问题,主要从

Jiassheng的博客 2153

.Net 内存溢出(System.OutOfMemoryException)的常见情况和处理方式总结

在什么情况下会出现OutOfMemonryException呢? 在我们试图新建一个对象时,而垃圾收集器又找不到任何可用内存时被抛出,这种情况下我们是可以捕获该异常的; 另一种情况是,CLR需要内存时,而却系统却不能提供,也会抛出该异常. 但此时,我们的应用程序是不能捕获该错误的.内存溢出(OutOfMemoryException)的调试分析32位操作系统的寻址空间是4G,其中有2G被操作系统

霍力强的专栏 4万+

PCB测试点

PCB测试点

qq_31444421的博客 1万+

决策大模型与生成式大模型有何不同?一文拆解技术框架与落地路径

大模型技术正从内容生成走向复杂场景的智能决策。与生成式大模型拟合概率分布不同,决策大模型以序列决策为核心,融合强化学习机制,在动态环境中感知反馈、持续修正行动路径。其技术框架涵盖语义理解、规划推理与闭环决策,并通过世界模型进行低成本仿真推演,显著提升供应链调度、物流排程等场景的应对效率。实际落地时需结合传统优化算法与人工兜底,构建“语义先导+数值寻优”的分层架构,才能平衡精度与稳定性。这篇内容拆解决策大模型的技术组成、落地路径与常见误区,为企业智能化转型提供可参考的实践框架。

weixin_29057163的博客 188

.Net内存泄露原因及解决办法

.Net内存泄露原因及解决办法   1.    什么是.Net内存泄露 (1).NET 应用程序中的内存 您大概已经知道,.NET 应用程序中要使用多种类型的内存,包括:堆栈、非托管堆和托管堆。这里我们需要简单回顾一下。 以运行库为目标的代码称为托管代码,而不以运行库为目标的代码称为非托管代码。 在运行库的控制下执行的代码称作托管代码。相反,在运行库之外运行的代码称作非托管代码...

weixin_33946020的博客 678

wifi/BT芯片RTL8723DS驱动移植和测试之一wifi篇

本文主要介绍如何在stm32mp157中移植并测试芯片RTL8723DS的wifi功能。

汉尼拔勇闯天涯 8741

Net 内存溢出(System.OutOfMemoryException)的常见情况和处理方式总结

在什么情况下会出现OutOfMemonryException呢? 在我们试图新建一个对象时,而垃圾收集器又找不到任何可用内存时被抛出,这种情况下我们是可以捕获该异常的; 另一种情况是,CLR需要内存时,而却系统却不能提供,也会抛出该异常. 但此时,我们的应用程序是不能捕获该错误的. 内存溢出(OutOfMemoryException)的调试分析 32位操作系统的寻址空间是4G,其中有2G被操作...

weixin_30384217的博客 6972

Linux ARM平台开发系列讲解(调试篇) 1.6.4 NVIDIA AGX Xavier以太网MAC TO MAC模式

内核发展了那么多年,早已经将这种场景集成到了内核里,具体添加方式如下,本次针对。具体详细描述,可参考本专栏的网络篇和交换机篇,这里就简单的提一句,想要使用。速率和双工状态固定死,使其和交换机的模式一模一样,双方就可以建立通信了。2. MAC TO MAC原理。3. 开启无PHY模式进入内核。模式,本章节记录调试过程。模式,简单来说就是字面意思,以太网部分需要与交换机。,其他芯片也是一样的。修改设备树文件,将与。

DSMGUOGUO的博客 1530

建立时间与保持时间

建立时间与保持时间的计算 文章目录1、建立时间与保持时间概述及模型2、寄存器之间数据传输时建立时间与保持时间3、寄存器之间数据传输时建立时间余量与保持时间余量计算4、 FPGA允许的最大时钟频率或最小时钟周期5、计算FPGA时钟所允许的最大频率或最小时钟周期6、违反建立和保持时间会发生什么? 1、建立时间与保持时间概述及模型 建立时间(Tsu): 在时钟采样之前,输入必须稳定一段时间,该时间量称为建立时间。 理想最优建立时间: 保持时间(Th): 在时钟沿之后输入到触发器稳定所需的最短时间。 理想最优

Crazzy_M的博客 3万+

分享.net常见的内存泄露及解决方法

关于内存泄漏的问题,之前也为大家介绍过,比如:《C++中内存泄漏的检测方法介绍》,是关于C++内存泄漏的。今天为大家介绍的是关于.NET内存泄漏的问题。   前段时间帮项目组内做了一次内存优化,产品是使用c#开发的winForm程序,一直以为.net提供了垃圾收集机制,开发的时候也没怎么注意内存的释放,导致最后的产品做出来之后,运行一个多小时就内存直接崩溃了,看来.net的垃圾收集还是得需要开发...

weixin_30699235的博客 316

【机械臂视觉抓取从理论到实战】

首先声明一下,此项目是参考B站哈萨克斯坦UP的【机械臂视觉抓取从理论到实战】 此内容为他研究生生涯的阶段性成果展示和技术分享,所有数据和代码均开源。所以鹏鹏我特此来复现一下,我采用的硬件与之有所不同,UP主使用UR5,我实验室采用的是UR3,下面列出相关材料 UR3CB3.12:https://www.universal-robots.cn/cb3/ 【UR3系统升级到CB3.12附带URcap1.05】硬件支持代码支持 jacquard数据集:https://pan.baidu.com/s/1524HrV

vor234的博客 5187

『内存泄露』在生产环境中,.Net如何定位系统内存泄露具体位置

📣读完这篇文章里你能收获到:生产环境排查内存问题的工具,排查命令的使用,排查经验分享

老陈聊架构 1873

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

分享.net常见的内存泄露及解决方法(转载)

2011-06-16 10:27 狩月 狩月的博客 字号:T | T 本文讨论的是.NET内存泄漏的问题,介绍了常见的内存泄漏和解决的办法,介绍的很详细,希望对你有帮助,一起来看。 AD:51CTO 网+ 第十二期沙龙:大话数据之美_如何用数据驱动用户体验   关于内存泄漏的问题,之前也为大家介绍过,比如:检测C++中的内存泄漏,是关于C++内存泄漏的。今天为大...

weixin_34345560的博客 399

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

WPF -.Net 4.0解决了DataGrid分组时的内存泄露

  在OpenExpressApp中框架自带一个【部门管理】模块,其中【功能权限】设置时用了DataGrid,并且使用了DataGrid的分组功能,UI如下: 用户反应在使用过程中,来回切换【业务对象】进行功能权限设置时,切换多次后会发现允许速度慢的和蜗牛一样。既然这么明显,打开任务管理器,未设置功能权限时内存消耗如下图为50496: 来回切换20次后,发现内存飚升为94580,如果模...

weixin_30914981的博客 162

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

一次.net托管内存泄露分析

简介:一次.net托管内存泄露分析最近协助分析了一个.net进程内存泄露的问题,过程分享给大家。 症状:客户的服务端.net进程出现分钟级的cpu抖动,接近100%后落回。 图1分析:支持同学通过procdump.exe工具抓取了进程dump, 设定触发dump的条件为,若进程的CPU使用量超过80%持续1秒,则开始抓取。procdump.exe -ma -s 1 -c 80 10672 f:\aliyunLoading Dump File [E:\temp\2

阿里云开发者 1899

使用Windbg快速分析应用内存泄露问题

Windbg程序调试是.NET高级开发需要掌握的必备技能,分析内存泄露、分析CPU高使用率、分析线程阻塞、分析内存对象、分析线程堆栈、Live Dedugging。这些Debug领域可以说一个技能+场景化应用的结合,如果只依靠Windbg几个简单的命令,不理解每个指令在实际Troubleshooting中的作用,是没有意义的。工欲善其事必先利其器,我们先从常用的命令和示例说起。 微软MVP实验室研究员 Windbg 常用命令 先准备一个Dump文件,建议使用64位应用程序。例如:64位II

微软技术栈 3919

net 内存泄露和内存溢出

一直以来都对内存泄露和内存溢出理解的不是很深刻。在网上看到了几篇文章,于是整理了一下自己对内存泄露和内存溢出的理解。 一.概念 内存溢出:指程序在运行的过程中,程序对内存的需求超过了超过了计算机分配给程序的内存,从而造成“Out of memory”之类的错误,使程序不能正常运行。 造成内存溢出有几种情况: 1.计算机本身的内存小,当同时运行多个软件时,计算机得内存不够用从而造成内存溢出。...

weixin_34248258的博客 122

Silverlight内存泄露(一)序

不知道有多少人遇到过Silverlight程序内存狂涨的状况,点击几个按钮、跳转几个页面程序的内存使用量一直上升。 即使最简单的程序,用silverlight模板,创建一个导航程序,跳转几次页面silverlight内存使用也再增加。 托管代码内存由GC回收,在silverlight、wpf出现之前内存泄露出现的比较少,但是silverlight程序却很容易发生内存泄露。 最近一直再处

1102

如何在.net应用中发现和避免内存和资源泄露

如何在.net应用中发现和避免内存和资源泄露 By Fabrice Marguerie 尽管很多人相信在.net应用中谈及内存及资源泄露是件很轻松的事情。但GC(垃圾回收器)并不是魔法师,并不能把你完全从小心翼翼处理内存与资源损耗中解放出来。 本文中我将解释缘何内存泄露依然存在以及如何避免其出现。别担心,本文不涉及GC内部工作机制及其它.net的资源及内存管理等高级特性中。 理解泄露本

三五月儿的专栏 4374

推荐文章:探索内存之谜 - .NET Memory Profiler 助力优化你的.NET应用

推荐文章:探索内存之谜 - .NET Memory Profiler 助力优化你的.NET应用 去发现同类优质开源项目:https://gitcode.com/ 在这个追求高性能、低内存消耗的时代,每一位.NET开发者都在寻找那把能揭开内存管理神秘面纱的钥匙。今天,我们为你带来了一位得力助手——.NET Memory Profiler,这是一款专为.NET生态系统打造的记忆侦探,它的存在,就是为了...

gitblog_09807的博客 1157

golang 切片截取 内存泄露_Go会出现内存泄露吗?如何避免?学会本文的方法足矣...

Go语言中文网,致力于每日分享编码、开源等知识,欢迎关注我,会有意想不到的收获!最近解决了我们项目中的一个内存泄露问题,事实再次证明pprof是一个好工具,但掌握好工具的正确用法,才能发挥好工具的威力,不然就算你手里有屠龙刀,也成不了天下第一,本文就是带你用pprof定位内存泄露问题。关于Go的内存泄露有这么一句话不知道你听过没有:10次内存泄露,有9次是goroutine泄露。我所解决的问题,也...

weixin_34221653的博客 446

WPF中解决内存泄露的几点提示与解决方法

一直以来用WPF做一个项目,但是开发中途发现内存开销太大,用ANTS Memory Profiler分析时,发现在来回点几次载入页面的操作中,使得非托管内存部分开销从起始的43.59M一直到150M,而托管部分的开销也一直持高不下,即每次申请的内存在结束后不能完全释放。在网上找了不少资料,甚受益,现在修改后,再也不会出现这种现象了(或者说,即使有也不吓人),写下几个小心得: 1. 慎用WPF样式...

weixin_30312659的博客 898

处理.NET中的内存泄露

Fabrice Marguerie是一位软件架构师和咨询师,他在MSDN发表了如何检测和避免.NET程序内存与资源泄漏的文章。此文章描述了编写.NET程序时可能发生的内存与资源泄漏,以及如何避免这些泄漏。 C#这样的编程语言使用垃圾收集器来清理内存,对于程序完全不会再访问的内存,本应是没有内存泄漏的。Fabrice称,内存泄漏发生在一块内存不 再被使用,但却依然被程序所引用时。当一块内存无法

飞龙在天 915
上一篇: Windbg 分析 Dump File 简单演示(转)
aqbeyond
博客等级 码龄22年 13粉丝 6原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值