CLR、托管、非托管 之一

ChatGPT Image 2025年8月19日 14_53_36

** CLR 与托管/非托管的关系**

  • CLR(Common Language Runtime) 是 .NET 的运行时环境:

    • 托管代码运行在 CLR 上,由它提供:

      • 内存管理(GC)
      • 类型安全
      • 异常处理
      • 安全控制
    • 非托管代码 不运行在 CLR 上,所以 CLR 不直接管理它,需要通过互操作(Interop)桥接:

      • P/Invoke(Platform Invoke) 调用 DLL
      • COM Interop 调用 COM 对象
  • 换句话说:

    • 托管代码/资源 → CLR 管理
    • 非托管代码/资源 → CLR 不管理,需要手动处理
    • CLR 只是管理托管世界的“保护者”,非托管世界 CLR 不干涉。

1️⃣ 托管 vs 非托管 —— 基础概念

(1)托管资源 / 托管代码

  • 托管代码(Managed Code)

    • 由 **.NET CLR(Common Language Runtime,通用语言运行时)** 执行和管理的代码。
    • 特点:CLR 提供内存管理(垃圾回收)、类型安全、异常处理、安全性等机制。
    • 示例:C#、VB.NET 写的代码在 .NET 下编译成 IL(中间语言),运行在 CLR 上就是托管代码。
  • 托管资源(Managed Resource)

    • 由 CLR 自动管理其生命周期的资源。

    • 典型例子:

      • 托管对象(C# 中的 class 实例,存放在堆上,由 GC 回收)
      • 托管内存(CLR 分配的堆内存)
      • 托管文件句柄、数据库连接(通过托管类封装)
    • 特点:开发者不需要手动释放,CLR 会自动回收。


(2)非托管代码 / 非托管资源

  • 非托管代码(Unmanaged Code)

    • 不受 CLR 直接管理的代码。

    • 一般是 操作系统原生代码传统编译语言生成的二进制

      • C、C++、汇编生成的 DLL 或 EXE。
    • 特点

      • 内存和资源管理由程序员自己控制(malloc/free、new/delete)。
      • 不具备 CLR 的类型安全、垃圾回收等保护机制。
  • 非托管资源(Unmanaged Resource)

    • CLR 或 .NET GC 无法自动管理的资源,需要程序员手动释放。

    • 典型例子:

      • 文件句柄(FileHandle)
      • 数据库连接(直接用 Win32 API)
      • 窗口句柄、套接字、GDI+ 对象、非托管内存
    • 使用注意

      • 必须在不需要时及时释放(例如实现 IDisposable.Dispose(),或者使用 using 块)。

2️⃣ 划分标准

分类 判断标准 典型示例 谁管理
托管代码 由 CLR 执行 C# IL、VB.NET IL CLR(垃圾回收)
非托管代码 不受 CLR 管理 C/C++ DLL 程序员/操作系统
托管资源 在托管堆或 CLR 控制下的资源 C# 对象实例、托管内存 CLR GC
非托管资源 CLR 无法控制的资源 文件句柄、数据库连接、非托管内存 程序员

3️⃣ 核心区别

区别点 托管 非托管
内存管理 CLR 自动回收 程序员手动管理
安全性 类型安全、有异常处理、沙箱保护 无类型安全,容易出错
生命周期 CLR GC 控制 开发者控制(容易泄漏)
调用方式 直接调用 P/Invoke 或 COM Interop
适用语言 C#, VB.NET 等 C, C++, Delphi 等

4️⃣ 使用注意事项

托管资源/代码

  • 不用手动释放内存(GC 会回收)。
  • 尽量避免非必要的对象创建,减少 GC 压力。
  • 对外部资源(文件、数据库、网络)仍然需要使用 IDisposableusing 来确保及时释放。

非托管资源/代码

  • 必须手动管理生命周期,避免资源泄漏。

  • 在托管代码中使用非托管资源,需要通过:

    • IDisposable + using 模式
    • SafeHandle / CriticalHandle 来安全封装非托管资源
    • P/Invoke 调用非托管函数时注意内存分配和释放
  • 需要注意异常安全,确保资源在异常时也能释放。


总结逻辑图(文字版):

[托管代码] --运行在--> CLR --管理--> [托管资源]
[非托管代码] --不受--> CLR 管理 --> [非托管资源]
托管代码 可通过 P/Invoke 调用 非托管代码/资源

posted @ 2025-08-19 15:03  青云Zeo  阅读(19)  评论(0)    收藏  举报