dotnet 警惕使用 StackTrace 加获取方法标记 Attribute 特性在 Release 下被内联
大家都知道,在 dotnet 里的 Debug 下和 Release 下的一个最大的不同是在 Release 下开启了代码优化。启用代码优化,将会对生成的 IL 代码进行优化,同时优化后的 IL 也会有一些运行时的更多优化。内联是一个非常常用的优化手段,内联将会让 StackTrace 获取的调用堆栈存在 Debug 下和 Release 下的差异,从而导致获取方法标记的 Attribute 特性不能符合预期工作
这一个坑是来源于我所在团队开源的 CUnit (中文单元测试框架) 仓库的一次单元测试过程,我发现了在 Debug 下能通过测试,但是在 Release 下失败。详细请看: https://github.com/dotnet-campus/CUnit/actions/runs/3327386251/jobs/5502313113
核心原因是在 CUnit (中文单元测试框架) 仓库里使用了 StackTrace 的方式获取调用堆栈,通过调用堆栈获取各个方法,找到标记了 TestMethodAttribute 的方法,定位到标记是单元测试的方法
在 Release 下,发现找不到任何一个标记了 TestMethodAttribute 的方法。通过日志输出可以看到在 Debug 下和 Release 下的调用堆栈是不相同的。在 Release 下少了几个方法,刚好这几个方法里面就包含了一个标记了 TestMethodAttribute 的方法
其原因是在 Release 下默认开启了代码优化,在代码优化时,将会尝试内联一些函数,导致了调用堆栈中存在一些函数是看不到的,因为这些函数在实际运行过程中是不存在的,被内联到其他方法里面去了。换句话说,即使不是在 Release 下,只要开启了代码优化,那么都可能因为代码优化让某些函数被内联,从而让调用堆栈看起来不符合预期
因此,使用 StackTrace 获取调用堆栈,将在不同的环境下可能存在一些差异,导致逻辑不符合预期。如果再需要从方法上,获取方法标记的特性,那这个逻辑自然是不靠谱的
规避方法有两个:
第一个,那就是不要这么使用,找找其他的方法
第二个是,如果没有其他的方法,那可以考虑在明确需要获取某个特性的函数上,标记 [MethodImpl(MethodImplOptions.NoInlining)] 表示此函数不要被内联
dotnet 警惕使用 StackTrace 加获取方法标记 Attribute 特性在 Release 下被内联的更多相关文章
- PHP 加解密方法大全
最近看见一篇文章讲的是PHP的加解密方法,正好也自己学习下,顺便以后有用到的地方也好能快速用上,仅供自己学习和复习,好了不多BB,上代码. 基于这几个函数可逆转的加密为:base64_encode() ...
- Linux系统的命令源码的获取方法
我们知道,Linux是开源的,它自带的功能强大的命令也是开源的,也就是说.我们能够获得这些命令的源码并研究它.那到底怎样获得系统的命令的源码呢? 命令的源码是一个软件包为单元的,放在一个软件包的源码中 ...
- Java方法内联
一.概念 方法内联就是把调用方函数代码"复制"到调用方函数中,减少因函数调用开销的技术 函数调用过程 1.首先会有个执行栈,存储它们的局部变量.方法名.动态连接 2.当一个方法 ...
- Java 方法内联
什么是Java 方法内联? 我们先来看看普遍的内联函数含义.在维基百科中解释为: 内联函数:在计算机科学中,内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,用来建议编译器对一些特殊函 ...
- 仅反射加载(ReflectionOnlyLoadFrom)的 .NET 程序集,如何反射获取它的 Attribute 元数据呢?
原文:仅反射加载(ReflectionOnlyLoadFrom)的 .NET 程序集,如何反射获取它的 Attribute 元数据呢? 平时我们获取一个程序集或者类型的 Attribute 是非常轻松 ...
- 先说一下JS的获取方法,其要比JQUERY的方法麻烦很多,后面以JQUERY的方法作对比。
先说一下JS的获取方法,其要比JQUERY的方法麻烦很多,后面以JQUERY的方法作对比. JS的方法会比JQUERY麻烦很多,主要则是因为FF浏览器,FF浏览器会把你的换行也当最DOM元素 复制代码 ...
- <经验杂谈>C#中一种最简单、最基本的反射(Reflection):通过反射获取方法函数
说起反射之前和很多用C#/.net的同仁们一样,相比于一般应用层对数据的增删改查总有点觉得深奥到难以理解.其实程序这东西,用过.实践过就很简单,我一直这么认为. 先说下概念:反射 Reflection ...
- c#图像处理入门(-bitmap类和图像像素值获取方法)
c#图像处理入门 -bitmap类和图像像素值获取方法 一.Bitmap类 Bitmap对象封装了GDI+中的一个位图,此位图由图形图像及其属性的像素数据组成.因此Bitmap是用于处理由像素数据定义 ...
- java 反射机制之 getDeclaredMethod()获取方法,然后invoke执行实例对应的方法
关于反射中getDeclaredMethod().invoke()的学习,来源于项目中的一行代码: SubjectService.class.getDeclaredMethod(autoMatchCo ...
- 【转】StackTraceElement获取方法调用栈的信息
本文链接:https://blog.csdn.net/hp910315/article/details/52702199 一.什么是StackTrace StackTrace(堆栈轨迹)存放的就是方法 ...
随机推荐
- 基于QGIS生产建筑物高度与遥感影像数据集
1. 概述 利用遥感影像推知建筑物高度是一经典研究,现有很多学者利用机器学习的方式,利用现有数据进行训练从而构建模型 本文旨在记述使用QGIS进行建筑物高度与遥感影像数据集的获取与制作 如果不想自己动 ...
- MySQL数据过滤和搜索
操作符 AND操作符 mysql> SELECT prod_id,prod_price,prod_name FROM products WHERE vend_id=1003 AND prod_p ...
- javascript雪花算法ID生成库simple-flakeid
开源地址:https://github.com/zhupengfeivip/simple-flakeId 核心算法版权属于 yitter](https://github.com/yitter)) ...
- #K-D Tree#洛谷 2093 [国家集训队]JZPFAR
题目 平面上有 \(n\) 个点.现在有 \(m\) 次询问,每次给定一个点 \((px, py)\) 和一个整数 \(k\), 输出 \(n\) 个点中离 \((px, py)\) 的距离第 \(k ...
- #排列组合,容斥#洛谷 5684 [CSPJX2019]非回文串
题目 分析 那显然就是\(n!\)减去回文串的方案数 首先如果有超过一个出现奇数次字母那肯定不存在回文串 如果有且仅有一个首先要在次数中选择一个然后其它当偶数处理 偶数那就是首先字母位置选好但顺序可以 ...
- 开发人员使用HANA交付业务的学习路径
本文于2019年7月22日完成,发布在个人博客网站上. 考虑个人博客因某种原因无法修复,于是在博客园安家,之前发布的文章逐步搬迁过来. 入门 编程规范. 开发环境使用方法. 基本语法,与其它同类软件的 ...
- C 语言函数:入门指南
C 语言中的函数声明和定义 您可以通过以下方式创建并调用函数: // 创建一个函数 void myFunction() { printf("我刚被执行了!"); } int mai ...
- 攻防世界 Mine- IDA静调或x64dbg动调 两种方式
刷攻防世界的最后一道二星题,记录一下,大佬请飘过 题目 分析过程 我很勇,我先双击看看这是什么 是一个扫雷游戏,第一下运气好没踩雷,发现无法继续输入了:如果运气不好,会输出"您踩雷啦!&qu ...
- std::thread 一:创建线程的三种方式
前言: #include <thread> thread.join() // 阻塞 thread.detach() // 非阻塞 thread.joinable() // bool,判断线 ...
- 阿里开源的32B大模型到底强在哪里?
阿里巴巴最近开源了一个320亿参数的大语言模型Qwen1.5-32B,网上都说很强很强,那么它到底强在哪里呢? 更高的性价比 Qwen1.5-32B中的B是billion的意思,也就是10亿,32B就 ...