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

【C#】详解C#中的内存管理机制

文章目录

  • 前言
  • 一、C#内存管理的基本机制
    • (1)托管堆(Managed Heap)
    • (2)垃圾回收(Garbage Collection)
    • (3)栈内存
  • 二、 开发者需要主动管理的场景
    • (1)非托管资源释放
    • (2)大对象和内存优化
    • (3)循环引用与内存泄漏
  • 三、手动干预GC的罕见场景
    • (1)强制触发GC
    • (2)弱引用(WeakReference)
  • 四、与非托管代码交互
  • 五、总结


前言

在C#中,内存管理主要通过 垃圾回收(Garbage Collection, GC) 机制自动完成,但开发者仍需在特定场景下关注资源释放和性能优化。以下是详细解析:

一、C#内存管理的基本机制

(1)托管堆(Managed Heap)

  • C#中的对象(引用类型)分配在托管堆上,由 CLR(Common Language Runtime) 自动管理。

  • 无需手动释放内存:垃圾回收器(GC)会周期性扫描托管堆,自动回收不再被引用的对象占用的内存。

(2)垃圾回收(Garbage Collection)

  • 分代回收:GC将对象分为三代(0/1/2代),新对象分配在0代。0代内存满时触发回收,存活对象晋升到下一代。

  • 非确定性回收:GC触发时机由CLR控制,开发者无法精确控制。

(3)栈内存

  • 值类型(如int、struct)分配在栈上,生命周期由作用域控制(方法结束时自动释放)。

二、 开发者需要主动管理的场景

虽然C#内存管理是自动的,但在以下场景仍需开发者介入:

(1)非托管资源释放

  • 问题:文件句柄、数据库连接、网络套接字等非托管资源(非CLR管理)需手动释放。

  • 解决方案:

    • 实现IDisposable接口,在Dispose()方法中释放资源。

    • 使用using语句确保资源及时释放:

    using (var file = File.Open("test.txt", FileMode.Open))
    {// 操作文件
    } // 自动调用file.Dispose()
    

(2)大对象和内存优化

  • 大对象堆(Large Object Heap, LOH):对象大小超过85KB时分配在LOH,LOH不会压缩,可能导致内存碎片。

  • 优化策略:

    • 避免频繁分配大对象(如缓存复用)。

    • 使用ArrayPool或对象池减少内存分配压力。

(3)循环引用与内存泄漏

  • 问题:若对象之间存在循环引用(如事件绑定未取消),即使对象不再使用,GC也可能无法回收。

  • 示例:

    public class Publisher
    {public event EventHandler Event;
    }public class Subscriber
    {public Subscriber(Publisher pub){pub.Event += HandleEvent; // 订阅事件}private void HandleEvent(object sender, EventArgs e) { }
    }// 使用后未取消订阅,Subscriber和Publisher会互相引用,无法被GC回收!
    
  • 解决:及时取消事件订阅(pub.Event -= HandleEvent)。

三、手动干预GC的罕见场景

(1)强制触发GC

  • 通过GC.Collect()手动触发回收,但通常不建议使用(影响性能)。

  • 适用场景:性能测试或内存泄漏调试。

(2)弱引用(WeakReference)

  • 允许对象被GC回收,同时保留访问能力:

    var weakRef = new WeakReference(new object());
    if (weakRef.IsAlive)
    {var obj = weakRef.Target; // 获取对象(可能已被回收)
    }
    

四、与非托管代码交互

  • 调用C/C++库或系统API时,需通过unsafe代码或Marshal类手动分配/释放内存:

    IntPtr buffer = Marshal.AllocHGlobal(1024); // 分配非托管内存
    // 使用buffer...
    Marshal.FreeHGlobal(buffer); // 手动释放
    

五、总结

  • 自动管理:C#通过GC自动回收托管堆内存,开发者无需手动释放。

  • 需关注的场景:

    • 非托管资源(文件、网络等)需通过IDisposable释放。

    • 避免内存泄漏(如循环引用、事件未取消)。

    • 优化大对象和频繁内存分配。

  • 工具辅助:使用内存分析工具(如Visual Studio Diagnostic Tools、JetBrains dotMemory)检测内存问题。

  • 代码示例:实现IDisposable

public class ResourceHolder : IDisposable
{private FileStream _file; // 非托管资源示例public ResourceHolder(string path){_file = File.Open(path, FileMode.Open);}public void Dispose(){_file?.Dispose(); // 释放资源GC.SuppressFinalize(this); // 避免重复回收}// 析构函数(备用,防止忘记调用Dispose)~ResourceHolder(){Dispose();}
}// 使用示例
using (var holder = new ResourceHolder("test.txt"))
{// 使用资源
}

掌握这些原则,可以更高效地利用C#的自动内存管理,同时避免常见陷阱。

相关文章:

【C#】详解C#中的内存管理机制

文章目录 前言一、C#内存管理的基本机制(1)托管堆(Managed Heap)(2)垃圾回收(Garbage Collection)(3)栈内存 二、 开发者需要主动管理的场景(1&am…...

C/S架构与B/S架构

一、定义与核心区别 C/S架构(Client/Server,客户端/服务器) 客户端需安装专用软件(如QQ、企业ERP系统),直接与服务器通信。服务器端通常包括数据库和业务逻辑处理1。特点:客户端承担部分计算任务…...

《DeepSeek MoE架构下,动态专家路由优化全解析》

在人工智能飞速发展的当下,模型架构的创新与优化始终是推动技术进步的关键力量。DeepSeek的混合专家模型(MoE)架构,以其独特的设计理念和卓越的性能表现,在大模型领域崭露头角。而其中的动态专家路由优化技术&#xff…...

Android双亲委派

下面是一份 Android 类加载器双亲委派机制的时序图示例,描述了当应用调用 loadClass() 时,各个加载器之间的委派过程。 #mermaid-svg-rBdlhpD2uRjBPiG8 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mer…...

go语言因为前端跨域导致无法访问到后端解决方案

前端服务8080访问后端8081这端口显示跨域了 ERROR Network Error AxiosError: Network Error at XMLHttpRequest.handleError (webpack-internal:///./node_modules/axios/lib/adapters/xhr.js:116:14) at Axios.request (webpack-internal:///./node_modules/axios/lib/core/A…...

Jmeter使用介绍

文章目录 前言Jmeter简介安装与配置JDK安装与配置JMeter安装与配置 打开JMeter方式一方式二 设置Jmeter语言为中文方法一(仅一次性)方法二(永久设置成中文) Jmeter文件常用目录 元件与组件元件组件元件的作用域元件的执行顺序第一个案例添加线程组添加 H…...

【商城实战(13)】购物车价格与数量的奥秘

【商城实战】专栏重磅来袭!这是一份专为开发者与电商从业者打造的超详细指南。从项目基础搭建,运用 uniapp、Element Plus、SpringBoot 搭建商城框架,到用户、商品、订单等核心模块开发,再到性能优化、安全加固、多端适配&#xf…...

Spring使用@Scheduled注解的参数详解

在现代Java开发中,定时任务是一个常见的需求。Spring框架提供了Scheduled注解,让我们能够以简单、直观的方式定义和管理这些定时任务。接下来,我们来深入探讨这个注解的使用,以及它的参数都有哪些含义和作用。 Scheduled注解可以…...

【网络】HTTP协议、HTTPS协议

HTTP与HTTPS HTTP协议概述 HTTP(超文本传输协议):工作在OSI顶层应用层,用于客户端(浏览器)与服务器之间的通信,B/S模式 无状态:每次请求独立,服务器不保存客户端状态(通过Cookie/Session扩展状态管理)。基于TCP:默认端口80(HTTP)、443(HTTPS),保证可靠传输。请…...

【Windows下Gitbook快速入门使用】

Windows下Gitbook快速入门使用 1 工具安装1.1 Node.js下载安装1.1 环境变量1.2 npm配置1.3 安装gitbook 2 gitbook使用2.1 gitbook 无法执行2.2 gitbook常用命令 Gitbook是一个软件,使用Git和Markdown来编排书本; GitBook helps you pushlish beautiful …...

创建Electron35 + vue3 + electron-builder项目,有很过坑,记录过程

环境: node v20.18.0 npm 11.1.0 用到的所有依赖: "dependencies": {"core-js": "^3.8.3","vue": "^3.2.13","vue-router": "^4.5.0"},"devDependencies": {"ba…...

FPGA 实验报告:四位全加器与三八译码器仿真实现

目录 安装Quartus软件 四位全加器 全加器、半加器 半加器: 全加器: 四位全加器电路图 创建项目 半加器 全加器 四位全加器 代码实现 半加器 全加器 四位全加器 三八译码器 创建项目 代码展示 modelsim仿真波形图 四位全加器 三八译码…...

动态规划详解(二):从暴力递归到动态规划的完整优化之路

目录 一、什么是动态规划?—— 从人类直觉到算法思维 二、暴力递归:最直观的问题分解方式 1. 示例:斐波那契数列 2. 递归树分析(以n5为例) 3. 问题暴露 三、第一次优化:记忆化搜索(Memoiza…...

前端学习——HTML

HTML VSCode常用快捷键HTML标签文本标签列表标签表格Form表单表单元素 块元素与行内元素新增标签 VSCode常用快捷键 代码格式化:ShiftAltF 向上或向下移动一行:AltUp或AltDown 快速复制一行代码:ShiftAltUp或者ShiftAltDown 快速替换&#x…...

12.【线性代数】——图和网络

十二 图和网络(线性代数的应用) 图 g r a p h { n o d e s , e d g e s } graph\{nodes, edges\} graph{nodes,edges}1.关联矩阵2. A A A矩阵的零空间,求解 A x 0 Ax0 Ax0 电势3. A T A^T AT矩阵的零空间,电流总结电流图结论 …...

[环境搭建篇] Windows 环境下如何安装repo工具

Windows 环境下如何安装repo工具 1. 安装前置依赖2. 配置Repo引导脚本方法一:通过Gitee镜像安装(推荐)方法二:通过清华镜像安装 3. 解决依赖问题4. 初始化Repo仓库5. 常见问题解决 前言: 在Windows环境下安装Repo工具需…...

LeetCode 热题 100_字符串解码(71_394_中等_C++)(栈)

LeetCode 热题 100_字符串解码(71_394) 题目描述:输入输出样例:题解:解题思路:思路一(栈): 代码实现代码实现(栈):以思路一为例进行调…...

「DataX」数据迁移-IDEA运行DataX方法总结

背景 业务需求希望把Oracle数据库中的数据,迁移至MySql数据库中,因为需要迁移全量和增量的数据,所以希望想用数据迁移工具进行操作。 经过一些调研查询,最终打算使用DataX进行数据的迁移。 DataX简单介绍 DataX 是阿里云 DataW…...

【 <一> 炼丹初探:JavaWeb 的起源与基础】之 Servlet 过滤器:实现请求的预处理与后处理

<前文回顾> 点击此处查看 合集 https://blog.csdn.net/foyodesigner/category_12907601.html?fromshareblogcolumn&sharetypeblogcolumn&sharerId12907601&sharereferPC&sharesourceFoyoDesigner&sharefromfrom_link <今日更新> 一、过滤器&…...

DeepSeek与浏览器自动化AI Agent构建指南

文章使用到的模型可以用硅基流动中的&#xff1a; 注册链接&#xff1a;硅基流动统一登录 邀请码&#xff1a;FytHp9Xa 一、技术选型阶段 1. 基础组件选择 AI模型&#xff1a;DeepSeek-R1开放API&#xff08;对话/推理&#xff09;或DeepSeek-Coder&#xff08;代码生成&#…...

面试中常问的mysql数据库指令【杭州多测师_王sir】

数据库中的修改表结构、增删改查、用户权限操作DDL 》数据库定义语言 create database&#xff0c;create table drop tableDML 》数据库操作语言 insert into&#xff0c;delete from&#xff0c;update set&#xff0c;DQL 》数据库查询语言 select .... from....crea…...

深度学习驱动的智能化革命:从技术突破到行业实践

第一章 深度学习的技术演进与核心架构 1.1 从浅层网络到深度学习的范式转变 深度学习的核心在于通过多层次非线性变换自动提取数据特征,其发展历程可划分为三个阶段:符号主义时代的规则驱动(1950s-1980s)、连接主义时代的浅层网络(1990s-2000s)以及深度学习时代的端到端…...

基于编译器特性浅析C++程序性能优化

最近在恶补计算机基础知识&#xff0c;学到CSAPP第五章的内容&#xff0c;在这里总结并且展开一下C程序性能优化相关的内容。 衡量程序性能的方式 一般而言&#xff0c;程序的性能可以用CPE&#xff08;Cycles Per Element&#xff09;来衡量&#xff0c;其指的是处理每个元素…...

服务器上通过ollama部署deepseek

2025年1月下旬&#xff0c;DeepSeek的R1模型发布后的一周内就火了&#xff0c;性能比肩OpenAI的o1模型&#xff0c;且训练成本仅为560万美元&#xff0c;成本远低于openAI&#xff0c;使得英伟达股票大跌。 下面我们来看下如何个人如何部署deepseek-r1模型。 我是用的仙宫云的…...

Android Coil总结

文章目录 Android Coil总结概述添加依赖用法基本用法占位图变形自定义ImageLoader取消加载协程支持缓存清除缓存监听 简单封装 Android Coil总结 概述 Coil 是一个用于 Android 的 Kotlin 图像加载库&#xff0c;旨在简化图像加载和显示的过程。它基于 Kotlin 协程&#xff0…...

《安富莱嵌入式周报》第351期:DIY半导体制造,工业设备抗干扰提升方法,NASA软件开发规范,小型LCD在线UI编辑器,开源USB PD电源,开源锂电池管理

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版&#xff1a; https://www.bilibili.com/video/BV16C95YEEZs 《安富莱嵌入式周报》第351期&#xff1a;DIY半导体…...

Redis在人员管理系统中的应用示例

用户会话管理 场景&#xff1a;用户登录后存储会话信息&#xff0c;支持多服务器共享 实现&#xff1a; 用户登录成功后&#xff0c;生成唯一Token&#xff08;如JWT&#xff09;&#xff0c;作为Redis的Key Value存储用户ID、角色、权限等信息&#xff0c;设置过期时间&…...

The Wedding Juicer POJ - 2227

采取从外层边界&#xff0c;一步一步向内部拓展的策略&#xff0c;具体来说&#xff0c;一开始将最外面一层的点加入队列&#xff0c;并标记这些点的坐标已经被访问 取出队列中高度最低的点&#xff0c;将其弹出&#xff0c;查看其上下左右的点&#xff0c;如果新点没有被访问…...

# 深入理解RNN(一):循环神经网络的核心计算机制

深入理解RNN&#xff1a;循环神经网络的核心计算机制 RNN示意图 引言 在自然语言处理、时间序列预测、语音识别等涉及序列数据的领域&#xff0c;循环神经网络(RNN)一直扮演着核心角色。尽管近年来Transformer等架构逐渐成为主流&#xff0c;RNN的基本原理和思想依然对于理…...

分布式锁—6.Redisson的同步器组件

大纲 1.Redisson的分布式锁简单总结 2.Redisson的Semaphore简介 3.Redisson的Semaphore源码剖析 4.Redisson的CountDownLatch简介 5.Redisson的CountDownLatch源码剖析 1.Redisson的分布式锁简单总结 (1)可重入锁RedissonLock (2)公平锁RedissonFairLock (3)联锁MultiL…...