朋友公司招聘用的一套C#基础面试题,10个码农8个错2个蒙,我也跳坑了…

朋友公司的一套面试题,很有意思,参见如下代码:

class Program{static void Main(string[] args){var t = Num();Console.WriteLine(t);Console.ReadLine();}static int Num(){int i = 10;try{return i;}finally{i = 11;Console.WriteLine($"i={i}");}}}

请问这段代码会输出什么?相信有一点编程经验的朋友都知道,答案是:output: i=11 ,接下来的一个问题是这个 Num() 方法的返回值是多少, 10 还是 11 ?相信有很多朋友就有点迷糊了,那答案是多少呢?在不运行程序的情况下,我们从 IL汇编角度 来寻找答案。

一:IL 上寻找答案

要想看 IL,可以用 ILSpy 反编译一下。

.method private hidebysig static int32 Num () cil managed 
{// Method begins at RVA 0x2074// Code size 39 (0x27).maxstack 2.locals init ([0] int32 i,[1] int32)IL_0000: nopIL_0001: ldc.i4.s 10IL_0003: stloc.0.try{IL_0004: nopIL_0005: ldloc.0IL_0006: stloc.1IL_0007: leave.s IL_0025} // end .tryfinally{IL_0009: nopIL_000a: ldc.i4.s 11IL_000c: stloc.0IL_000d: ldstr "i={0}"IL_0012: ldloc.0IL_0013: box [mscorlib]System.Int32IL_0018: call string [mscorlib]System.String::Format(string, object)IL_001d: call void [mscorlib]System.Console::WriteLine(string)IL_0022: nopIL_0023: nopIL_0024: endfinally} // end handlerIL_0025: ldloc.1IL_0026: ret
} // end of method Program::Num

对比 return i 生成的 IL 代码,它的做法是将 i 保存到了一个临时变量 loc.1 处,最后将 loc.1 处的变量返回出去,我们很惊讶的发现 finally 块中并没有对 loc.1 处的变量赋值,也就是没有 stloc.1 指令,综合下来结果应该是 10, 而不是 11。

不知道可有朋友发现,这里的跳转指令 IL_0007: leave.s IL_0025 ,貌似直接跳过了 finally 块,那到底有没有执行呢?这个从 IL 上看不出,只能从 汇编角度 看啦。

二:查看汇编

接下来祭出windbg,汇编代码如下:

0:006> !U /d 008608a8
Normal JIT generated code
ConsoleApp1.Program.Num()
Begin 008608a8, size aaD:\net5\ConsoleApp1\ConsoleApp1\Program.cs @ 23:
008608d4 c745e40a000000  mov     dword ptr [ebp-1Ch],0AhD:\net5\ConsoleApp1\ConsoleApp1\Program.cs @ 26:
008608db 90              nopD:\net5\ConsoleApp1\ConsoleApp1\Program.cs @ 27:
008608dc 8b45e4          mov     eax,dword ptr [ebp-1Ch]
008608df 8945e0          mov     dword ptr [ebp-20h],eax
008608e2 90              nop
008608e3 c745ec00000000  mov     dword ptr [ebp-14h],0
008608ea c745f0fc000000  mov     dword ptr [ebp-10h],0FCh
008608f1 6849098600      push    860949h
008608f6 eb00            jmp     008608f8D:\net5\ConsoleApp1\ConsoleApp1\Program.cs @ 30:
008608f8 90              nopD:\net5\ConsoleApp1\ConsoleApp1\Program.cs @ 31:
008608f9 c745e40b000000  mov     dword ptr [ebp-1Ch],0BhD:\net5\ConsoleApp1\ConsoleApp1\Program.cs @ 32:
00860900 b9a8429778      mov     ecx,offset mscorlib_ni+0x142a8 (789742a8) (MT: System.Int32)
00860905 e8ea27daff      call    006030f4 (JitHelp: CORINFO_HELP_NEWSFAST)
0086090a 8945dc          mov     dword ptr [ebp-24h],eax
0086090d 8b0544235d03    mov     eax,dword ptr ds:[35D2344h] ("i={0}")
00860913 8945d4          mov     dword ptr [ebp-2Ch],eax
00860916 8b45dc          mov     eax,dword ptr [ebp-24h]
00860919 8b55e4          mov     edx,dword ptr [ebp-1Ch]
0086091c 895004          mov     dword ptr [eax+4],edx
0086091f 8b45dc          mov     eax,dword ptr [ebp-24h]
00860922 8945d0          mov     dword ptr [ebp-30h],eax
00860925 8b4dd4          mov     ecx,dword ptr [ebp-2Ch]
00860928 8b55d0          mov     edx,dword ptr [ebp-30h]
0086092b e820d74c78      call    mscorlib_ni!System.String.Format(System.String, System.Object)$##6000545 (78d2e050)
00860930 8945d8          mov     dword ptr [ebp-28h],eax
00860933 8b4dd8          mov     ecx,dword ptr [ebp-28h]
00860936 e829465b78      call    mscorlib_ni!System.Console.WriteLine(System.String)$##6000B79 (78e14f64)
0086093b 90              nopD:\net5\ConsoleApp1\ConsoleApp1\Program.cs @ 33:
0086093c 90              nop
0086093d 58              pop     eax
0086093e ffe0            jmp     eaxD:\net5\ConsoleApp1\ConsoleApp1\Program.cs @ 34:
00860940 8b45e0          mov     eax,dword ptr [ebp-20h]
00860943 8d65fc          lea     esp,[ebp-4]
00860946 5f              pop     edi
00860947 5d              pop     ebp
00860948 c3              retD:\net5\ConsoleApp1\ConsoleApp1\Program.cs @ 22:
00860949 c745f000000000  mov     dword ptr [ebp-10h],0
00860950 ebee            jmp     00860940

为了方便比对,我再把代码行数给截出来。

c5a084596043f268c10e16373ab843c7.png

一般函数的返回值都是放在 eax 中,所以重点关注下 eax 的赋值部分,仔细观察它的路径大概就是下面四句代码:

mov     dword ptr [ebp-1Ch],0Ah
mov     eax,dword ptr [ebp-1Ch]
mov     dword ptr [ebp-20h],eax
mov     eax,dword ptr [ebp-20h]

也就是说,最后的 eax 还是当初的 0Ah= 10, 也和 IL 反映出来的一致,return 操作的底层会将返回值放到一个 临时区域 = ebp-20h 中,最后返回 临时区域 中的值。

再回到刚才 IL 部分的疑问,从上面的 jmp 008608f8 指令看,return 的下一步就直接进了 finally 块,最后执行 RET 弹出下一行代码指令到 EIP 中完成方法体的执行,大概就是这个样子。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/289703.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【原创】ucos信号量的操作及原理

信号量的操作及原理 1.OSSemCreate创建信号量semaphore在使用信号量之前,要先用OSSemCreate创建一个信号量,并通过返回的合法事件结构体指针使用信号量。OS_EVENT *OSSemCreate(INT16U cnt){#if OS_CRITICAL_METHOD 3 /* 原理请查看http://blog.csdn.ne…

JMeter之JMS接口测试

JMeter中的JMS Point-to Point、JMS Publisher和JMS Subscriber分别用于发送JMS的PTP消息和PUB/SUB消息,可以选择使用JMeter来测试JMS。 MOM(消息中间件)作为消息数据交换的平台,也是影响应用执行效率的潜在环节。在Java程序中&am…

AutoRest - 具有 C# 和 Razor 模板的 Swagger 规范代码生成器。

简介AutoRest工具生成用于访问 RESTful Web 服务的客户端库。AutoRest是使用OpenAPI 规范格式描述 REST API 的规范。AutoRest 是一个提供代码生成框架的工具,用于将 OpenAPI 2.0 和 3.0 规范转换为客户端库,用于这些规范所描述的服务。它是在 OpenAPI I…

java内存四大区,jvm基础-内存区域

1.运行时数据区java虚拟机在执行java程序的过程中会爸它所管理的内存分为若干个不同的数据区域jvm内存主要分为堆、程序计数器、方法区、虚拟机栈喝本地方法栈,直接内存等。java方法的运行和虚拟机栈虚拟机栈是线程运行java方法所需要的数据,指令&#x…

【ArcGIS遇上Python】ArcGIS Python实现批量化矢量和栅格数据重命名

在ArcGIS中,要为矢量数据或栅格数据重命名,需要到ArcCatalog中进行,但是只能一个个重命名。ArcGIS中也提供了矢量、栅格数据的重命名工具:【重命名】,如下图所示: 双击运行该工具,可以看到,更改数据集的名称。这包括各种数据类型,其中包括要素数据集、栅格、表 和 sha…

电脑测速软件_网速慢,怎么办,教你测速,教你解决方案

网速慢、网页慢、视频卡、游戏卡,如何判断自己的宽带速率是否有问题,本期我们来讨论下,如何正确测试网速,信道干扰、2.4G与5G信号、IPTV测速。一、电脑测速受到无线环境影响,无线性能瓶颈等多方面原因,电脑…

Xamarin效果第十六篇之GIS添加Mark

在前面几篇文章中简单玩耍了一下在线和离线加载高德地图图层;今天再次完善一下添加Mark图层和展示详细信息弹窗;来看看最终效果:添加Mark无非就是用了PictureMarkerSymbol:PictureMarkerSymbol picMarkSymbol await GetPictureMarker(); MapPoint mapPoint new MapPoint(foot…

Android规范发展

一、Android 编码规范 1.java 代码中不出现中文。最多凝视中能够出现中文 2.局部变量命名、静态成员变量命名 仅仅能包括字母,单词首字母出第一个外,都为大写,其它字母都为小写 3.常量命名 仅仅能包括字母和_,字母所有大写&#x…

js input 自动换行_矿用自动灭火装置水基型自动灭火装置原理国内分析研讨_搜狐汽车...

山 东潍坊九通消防科技(九通长胜)是国内最早针对矿用车辆发动机舱自动灭火的要求研发设计的超细干粉、水基型自动灭火装置是当下国内解决矿用车辆(地表车辆、井下车辆)灭火的非常好的技术,目前在掘进机、凿岩台车、皮卡、吉普车、轻卡、巨无霸、电传动汽车、露天矿山…

关于WannaCry勒索病毒 你需要知道的8个问题

近日来,WannaCry勒索病毒席卷全球,超过150个国家至少30万名用户中招,造成损失达80亿美元(约合人民币550亿元)。 目前,多名网络安全专家指出,目前病毒事态只是由于多种原因而稍显缓和,但许多网络用户特别是中…

C# ReaderWriterLockSlim类

为了使锁定机制允许锁定多个读取器(而不是一个写入器)访问某个资源,可以使用 ReaderWriterLockSlim 类。这个类提供了一个锁定功能,如果没有写入器锁定资源,就允许多个读取器访问资源,但只能有一个写入器锁定该资源。ReaderWriter…

LOG4NET用法

log 4net组件下载:log4net.dll web.config配置如下&#xff1a; <?xml version"1.0" encoding"utf-8" ?> <configuration><configSections><section name"log4net" type"log4net.Config.Log4NetConfigurationSectio…

怎么计算信息完整度_德阳冻货运镖怎么计算费用

德阳冻货运镖怎么计算费用物流”一词我们并不陌生&#xff0c;它把小到零食玩具、大到家用电器&#xff0c;一一送到我们手中&#xff0c;但传统的物流运输模式只能满足部分物品的运输要求。随着人们的生活品质不断提高、消费不断升级。德阳冻货运镖怎么计算费用息平台的支撑&a…

AI+时代,谈谈产品经理对图像识别技术的阈值控制

产品满足用户的需求有一个阈值&#xff0c;产品值低于阈值用户会觉得了无生趣&#xff0c;即产品一般般&#xff0c;也即产品经理做了功能经理。产品值等于阈值产品功能基本满足了用户的需求&#xff0c;而只有产品经理驾驭了需求&#xff0c;把产品做成作品&#xff0c;产品值…

【亲身经验】如何在 6 个月内成为“微软 MVP”

前言很荣幸&#xff0c;在愚人节这天&#x1f601;&#xff0c;收到了获得“微软 MVP”奖项的通知&#xff1a;由于该奖项评选标准只涉及 2021 年所做的贡献&#xff0c;而我的贡献主要是公众号文章。因此以我从 2021/06 开始运营个人公众号算起&#xff0c;可以说&#xff0c;…

3500个常用汉字表_小学常用560个汉字笔画笔顺表,打印下来,小学六年慢慢练...

温馨提示公众号改版后很多孩子及家长朋友找不到我们了为了方便大家更快地找到我们获取更多学习工具和资料您可以按照下面的方式 星标或置顶我们☟ ☟ ☟小学阶段&#xff0c;字写得好很重要&#xff0c;笔顺写对了也很重要。写对笔顺有利于把字写得美观&#xff0c;考试时碰到笔…

SVN安装和使用总结

SVN简介&#xff1a; 为什么要使用SVN&#xff1f; 程序员在编写程序的过程中&#xff0c;每个程序员都会生成很多不同的版本&#xff0c;这就需要程序员有效的管理代码&#xff0c;在需要的时候可以迅速&#xff0c;准确取出相应的版本。 Subversion是什么&#xff1f; 它是一…

从部署 httpd 入手,理清 k8s 配置中的 containerPort、port、nodePort、targetPort

注&#xff1a;文中各种内网、公网 IP 仅为示例&#xff0c;不保证所有 IP 都可以访问&#xff0c;且你的环境中 IP 可能不同。背景在上一篇文章 自己搭建一个k8s环境 中&#xff0c;我们一顿操作猛如虎&#xff0c;搭建出了由 1 个 master 和 1 个 worker 节点组成的 k8s 集群…

360文件粉碎机_中山三乡资料文件销毁粉碎销毁资料文件公司一览表

中山三乡资料文件销毁粉碎销毁资料文件公司一览表安排搬运工作人员及运输车辆上门收取销毁物品&#xff0c;将需销毁的物品装上运输车辆&#xff0c;并进行拍照、车箱粘贴封条等工作。第五步&#xff1a;客户可安排工作人员&#xff0c;跟我公司销毁运输车辆一同前往我公司销毁…