当前位置: 首页 > news >正文

【C#】内存的使用和释放

在 C# 中,内存管理主要是由 .NET 的垃圾回收器(Garbage Collector, GC)自动处理的。然而,了解如何正确地使用和释放内存对于编写高效且可靠的代码非常重要。以下是一些关键点和最佳实践:

1. 内存分配

  1. 托管资源

    • 托管资源是由 CLR 自动管理的,例如对象实例、字符串等。
    • 当创建一个对象时,CLR 会从托管堆中分配内存。
  2. 非托管资源

    • 非托管资源包括文件句柄、数据库连接、GDI+ 对象等。
    • 这些资源需要显式地释放,通常通过实现 IDisposable 接口来完成。

2. 内存释放

  1. 垃圾回收器

    • 垃圾回收器定期运行,查找不再被引用的对象,并回收它们占用的内存。
    • 垃圾回收器将内存分为三代(Gen 0, Gen 1, Gen 2),根据对象的生命周期进行不同的处理。
  2. 终结器(Finalizer)

    • 终结器是一个特殊的方法,用于在对象被垃圾回收之前执行清理工作。
    • 终结器通常用于释放非托管资源,但不推荐频繁使用,因为它们会增加垃圾回收的复杂性和开销。
  3. IDisposable 接口

    • 实现 IDisposable 接口可以显式地控制资源的释放。
    • 使用 using 语句可以确保资源在作用域结束时被正确释放。

3. 示例代码

3.1 托管资源的使用和释放

public class ManagedResource
{// 构造函数public ManagedResource(){Console.WriteLine("ManagedResource created.");}// 析构函数(可选)~ManagedResource(){Console.WriteLine("ManagedResource finalized.");}
}public class Program
{static void Main(){ManagedResource resource = new ManagedResource();// 使用资源...// 资源会在适当的时候被垃圾回收器自动回收}
}

3.2 非托管资源的使用和释放

using System;public class UnmanagedResource : IDisposable
{private IntPtr _handle; // 模拟非托管资源private bool _disposed = false;public UnmanagedResource(){_handle = IntPtr.Zero; // 分配非托管资源Console.WriteLine("UnmanagedResource created.");}public void Dispose(){Dispose(true);GC.SuppressFinalize(this);}protected virtual void Dispose(bool disposing){if (!_disposed){if (disposing){// 释放托管资源}// 释放非托管资源if (_handle != IntPtr.Zero){// 释放非托管资源Console.WriteLine("UnmanagedResource released.");_handle = IntPtr.Zero;}_disposed = true;}}~UnmanagedResource(){Dispose(false);}
}public class Program
{static void Main(){using (var resource = new UnmanagedResource()){// 使用资源...}// 资源在 using 语句块结束时被自动释放}
}

4. 最佳实践

  1. 使用 using 语句

    • 对于实现了 IDisposable 接口的对象,使用 using 语句确保资源在作用域结束时被正确释放。
  2. 避免不必要的对象创建

    • 尽量减少临时对象的创建,特别是在循环中。
  3. 及时释放非托管资源

    • 如果类使用了非托管资源,确保实现 IDisposable 接口,并在 Dispose 方法中释放这些资源。
  4. 避免显式调用 GC.Collect()

    • 除非有明确的理由,否则不要显式调用 GC.Collect(),因为这会影响性能并干扰垃圾回收器的正常工作。
  5. 避免滥用终结器

    • 只有在确实需要释放非托管资源时才使用终结器。大多数情况下,应优先使用 IDisposable 接口。
  6. 使用弱引用

    • 对于那些可以被垃圾回收器回收的对象,可以考虑使用 WeakReference 类,以避免强引用导致对象无法被回收。

通过遵循这些最佳实践,可以更有效地管理和优化 C# 应用程序中的内存使用。

5. 解决内存已损坏

【C#】未处理System.AccessViolationExceptionHResult=-2147467261Message=尝试读取或写入受保护的内存。这通常指示其他内存已损坏。_system.accessviolationexception:“尝试读取或写入受保护的内存。这通常-CSDN博客文章浏览阅读1.3k次,点赞9次,收藏10次。【C#】未处理System.AccessViolationExceptionHResult=-2147467261Message=尝试读取或写入受保护的内存。这通常指示其他内存已损坏。_system.accessviolationexception:“尝试读取或写入受保护的内存。这通常指示其他https://blog.csdn.net/wangnaisheng/article/details/139679402

 

相关文章:

  • AWS 管理控制台
  • 打造高质量软件架构 - 9大质量属性
  • [Linux]磁盘分区指令
  • 网络安全全方略
  • Python 爬虫 根据ID获得UP视频信息
  • Linux驱动开发(速记版)--并发与竞争
  • 【HDP】zookeeper未授权漏洞修复
  • debian 12配置固定ip
  • vuepress 浏览器加载缓存,总是显示旧页面,无法自动刷新数据的解决方法
  • JVM常见面试题
  • 足底筋膜炎的症状
  • 2024ICPC网络赛第一场C. Permutation Counting 4(线性代数)
  • 【程序员必读】近年来编程提效工具大合集。小白必看!
  • 9月26日day16
  • 望繁信科技CTO李进峰受邀在上海外国语大学开展流程挖掘专题讲座
  • 分享一款快速APP功能测试工具
  • 【108天】Java——《Head First Java》笔记(第1-4章)
  • 【159天】尚学堂高琪Java300集视频精华笔记(128)
  • 【许晓笛】 EOS 智能合约案例解析(3)
  • android图片蒙层
  • Idea+maven+scala构建包并在spark on yarn 运行
  • Java 9 被无情抛弃,Java 8 直接升级到 Java 10!!
  • java8-模拟hadoop
  • JS创建对象模式及其对象原型链探究(一):Object模式
  • Spring Cloud Feign的两种使用姿势
  • use Google search engine
  • - 概述 - 《设计模式(极简c++版)》
  • 扑朔迷离的属性和特性【彻底弄清】
  • 前端学习笔记之原型——一张图说明`prototype`和`__proto__`的区别
  • 如何合理的规划jvm性能调优
  • 设计模式走一遍---观察者模式
  • 思维导图—你不知道的JavaScript中卷
  • 腾讯大梁:DevOps最后一棒,有效构建海量运营的持续反馈能力
  • 腾讯视频格式如何转换成mp4 将下载的qlv文件转换成mp4的方法
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • ​​​​​​​STM32通过SPI硬件读写W25Q64
  • ​一帧图像的Android之旅 :应用的首个绘制请求
  • #在 README.md 中生成项目目录结构
  • (52)只出现一次的数字III
  • (C语言)输入一个序列,判断是否为奇偶交叉数
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (待修改)PyG安装步骤
  • (附源码)ssm本科教学合格评估管理系统 毕业设计 180916
  • (附源码)计算机毕业设计SSM疫情居家隔离服务系统
  • (函数)颠倒字符串顺序(C语言)
  • (三)SvelteKit教程:layout 文件
  • (四)stm32之通信协议
  • (转)IIS6 ASP 0251超过响应缓冲区限制错误的解决方法
  • (转)程序员技术练级攻略
  • .java 9 找不到符号_java找不到符号
  • .net core 源码_ASP.NET Core之Identity源码学习
  • .NET Core工程编译事件$(TargetDir)变量为空引发的思考
  • .Net程序帮助文档制作
  • .NET高级面试指南专题十一【 设计模式介绍,为什么要用设计模式】
  • .net利用SQLBulkCopy进行数据库之间的大批量数据传递