首页 > 编程语言 >C# DebuggerAttribute在Debug/Release下GC 对象回收的影响

C# DebuggerAttribute在Debug/Release下GC 对象回收的影响

时间:2023-09-05 20:14:06浏览次数:36  
标签:assembly C# System Subscriber Test GC Release EventTest Debug

一、DebuggerAttribute

DebuggerAttribute为作用在程序集上的特性,按照微软文档对该特性的描述,该特性用于修改运行时实时 (JIT) 调试的代码生成。而在Debug下编译并生成的程序集,JIT会将变量保存至方法结束。这将影响以下代码的一些表现。

1、Debug

程序集在Debug模式下默认的DebuggerAttribute如下,通过ILspy可以看到。

// D:\vs2019 proj\EventTest\EventTest\bin\Debug\net6.0\EventTest.dll
// EventTest, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null
// Global type: <Module>
// Entry point: EventTest.Program.Main
// Architecture: AnyCPU (64-bit preferred)
// Runtime: v4.0.30319
// This assembly was compiled using the /deterministic option.
// Hash algorithm: SHA1
// Debug info: Loaded from portable PDB: D:\vs2019 proj\EventTest\EventTest\bin\Debug\net6.0\EventTest.pdb

using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default | DebuggableAttribute.DebuggingModes.DisableOptimizations | DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints | DebuggableAttribute.DebuggingModes.EnableEditAndContinue)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("EventTest")]
[assembly: AssemblyConfiguration("Debug")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EventTest")]
[assembly: AssemblyTitle("EventTest")]
[assembly: AssemblyVersion("1.0.0.0")]
ILspy on assembly

控制台应用程序的Main函数是这样的。

    private class TestClass
    {
        public void Test()
        {
            Subscriber sub = new Subscriber();
            sub = null;
            GC.Collect();
        }
    }

    private static void Main(string[] args)
    {
        TestClass testClass = new TestClass();
        testClass.Test();
        Console.WriteLine("Test方法结束");
        Console.ReadLine();
        Debugger.Break();
    }
public class Subscriber
{
    public Subscriber()
    {
        Console.WriteLine("Subscriber created");
    }

    public void Subscribe(object o, EventArgs e)
    {
        Console.WriteLine("Subscriber " + DateTime.Now);
    }

    ~Subscriber()
    {
        Console.WriteLine("Subscriber Finalize");
    }
}
Subscriber

 

//Output
Subscriber created
Test方法结束

运行后将不会看到Subscriber的终结器被执行。

2、Release

将以上代码以Release模式下编译后运行。在程序结束前执行了Subscriber的终结器。

//Output
Subscriber created
Test方法结束
Subscriber Finalize

Release模式下的DebuggerAttribute。

using System.Diagnostics;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.Versioning;

[assembly: CompilationRelaxations(8)]
[assembly: RuntimeCompatibility(WrapNonExceptionThrows = true)]
[assembly: Debuggable(DebuggableAttribute.DebuggingModes.IgnoreSymbolStoreSequencePoints)]
[assembly: TargetFramework(".NETCoreApp,Version=v6.0", FrameworkDisplayName = ".NET 6.0")]
[assembly: AssemblyCompany("EventTest")]
[assembly: AssemblyConfiguration("Release")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: AssemblyInformationalVersion("1.0.0")]
[assembly: AssemblyProduct("EventTest")]
[assembly: AssemblyTitle("EventTest")]
[assembly: AssemblyVersion("1.0.0.0")]
ILspy on assembly with release mode

二、在Debug下回收对象

1、在Test()方法外回收

前文提过,在Debug下编译并生成的程序集,JIT会将变量保存至方法结束,所以TestClass.Test()方法中的GC.collect()没有把对象回收掉。那么在Test()方法结束后再执行一次回收即可把GC.Collect()即可把对象回收掉。
注:其实不管是Debug还是在Release下,TestClass.Test()方法中的Subscriber对象在线程离开Test()方法后会被变为无根对象,其所占用的内存空间在下一次GC的时候回收。

2、在Test()方法内回收

既然是通过DebuggerAttribute影响JIT对变象的保存,那么在Debug模式下指定DebuggerAttribute即可改变JIT的前述的行为。

//MyAssemblyInfo.cs
using System.Diagnostics;

[assembly: Debuggable(DebuggableAttribute.DebuggingModes.Default)]
MyAssemblyInfo.cs

在项目中新建文件,内容如上。(注:如果是Net framework项目,可以在项目自带的AssemblyInfo加入以上内容)

将DebuggingModes指定为Default即可让Subscriber对象在Test内回收。终结器的执行顺序在Test方法之后是因为执行终结器的时机是由GC决定,并不由程序员决定。

//Output
Subscriber created
Test方法结束
Subscriber Finalize

 

 

更多信息查看以下链接:

终结器 - C# 编程指南 - C# | Microsoft Learn

GC.Collect 方法 (System) | Microsoft Learn

DebuggableAttribute 类 (System.Diagnostics) | Microsoft Learn

DebuggableAttribute.DebuggingModes 枚举 (System.Diagnostics) | Microsoft Learn

C # 编译器选项 - 代码生成选项 - C# | Microsoft Learn

标签:assembly,C#,System,Subscriber,Test,GC,Release,EventTest,Debug
From: https://www.cnblogs.com/mikodopants/p/17680550.html

相关文章

  • c++/c中关于头文件的探索
    //Fin.h#ifndefFIN_H#defineFIN_Hintadd(inta,intb);#endif//Fin.cpp#include"Fin.h"intadd(inta,intb){returna+b;}//Test1.cpp#include<iostream>#include"Fin.h"//包含Fin.h来调用函数intmain(){......
  • 2023你需要使用的最佳VSCode扩展
    VisualStudioCode(VSCode)是一款广受欢迎的多功能代码编辑器,在最新的StackOverflow开发者调查中,近75%的开发者将其选为首选集成开发环境。VSCode提供了一系列开箱即用的特性和功能,但其真正的威力在于市场上庞大的扩展生态系统。整理了VSCode30大扩展列表,希望大家能使用这些......
  • 海洋cms的播放器的播放参数
    1播放/下载地址规范格式:集数$地址$后缀  例如:第一集$http://www/xxx.com/video/1.mp4$ckplayer  备注:每行一集,地址必读包含 集数、地址、后缀三个部分,并且用$隔开  特殊格式播放器,如云盘下载、弹幕播放器,用英文逗号","隔开。如:  云盘下载播放器(无密码):https://pan......
  • scrum敏捷开发-传统开发方式的颠覆者
    在当今高度变化的时代,软件开发的环境和要求也在不断变化。传统的开发方法往往难以适应这种快速变化,因此,一种新的软件开发方法——敏捷开发逐渐得到了广泛的关注和应用。本文将介绍敏捷开发的概念、优势、实践经验、敏捷开发工具以及注意事项,帮助您更好地了解和运用敏捷开发。一、敏......
  • 如何在Nuxt 3中为<html>和<body>标签添加Tailwind CSS类?
    在Nuxt3中为<html>和<body>标签添加TailwindCSS类,可以参考以下步骤:安装TailwindCSS:在项目根目录下运行以下命令安装TailwindCSS和其依赖:npminstalltailwindcss@latest@tailwindcss/typography@latestpostcss@latestautoprefixer@latest创建TailwindCSS配置......
  • 无涯教程-JavaScript - DAYS360函数
    描述DAYS360函数返回基于360天的年份(十二个月为30天)的两个日期之间的天数,该天数用于会计计算。语法DAYS360(start_date,end_date,[method])争论Argument描述Required/OptionalStart_dateThetwodatesbetweenwhichyouwanttoknowthenumberofdays.Requir......
  • 【愚公系列】2023年09月 WPF控件专题 Calendar控件详解
    (文章目录)前言WPF控件是WindowsPresentationFoundation(WPF)中的基本用户界面元素。它们是可视化对象,可以用来创建各种用户界面。WPF控件可以分为两类:原生控件和自定义控件。原生控件是由Microsoft提供的内置控件,如Button、TextBox、Label、ComboBox等。这些控件都是WPF中常见......
  • [MSSQL]开启/关闭Ad Hoc Distributed Queries组件
    SQLServer阻止了对组件“AdHocDistributedQueries”的STATEMENT“OpenRowset/OpenDatasource”的访问开启组件:execsp_configure'showadvancedoptions',1reconfigureexecsp_configure'AdHocDistributedQueries',1reconfigure关闭组件:execsp_configur......
  • k8s之PV、PVC
    1.前言在k8s中,管理存储一直就是管理计算实例的问题。PersistentVolume系统为用户和集群管理人员提供了两个API,这两个API为用户屏蔽了底层存储的细节。这两个API对象就是PersistentVolume和PersistentVolumeClaim。2.介绍PV是集群中的存储资源,由管理员提供或者通过storagecl......
  • C# 二进制转base64
     publicstaticstringConvertUploadFileToBase64(HttpPostedFileBasefile){using(MemoryStreammemoryStream=newMemoryStream()){file.InputStream.CopyTo(memoryStream);byte[]binaryData......