草庐IT

c# - Reflection.Emit.ILGenerator异常处理 "Leave"指令

coder 2024-06-03 原文

首先,一些背景信息:

我正在为学校项目制作编译器。它已经在工作了,我正在花费大量精力来修复错误和/或优化它。我最近遇到了一个问题,我发现当您调用以下任何成员方法时,ILGenerator 对象会生成一个额外的 leave 指令:

BeginCatchBlock()
BeginExceptFilterBlock()
BeginFaultBlock()
BeginFinallyBlock()
EndExceptionBlock()

因此,您通过调用 BeginExceptionBlock() 开始一个 try 语句,使用 BeginCatchBlock() 添加几个 catch 子句,可能添加一个带有 的 finally 子句code>BeginFinallyBlock(),然后用 EndExceptionBlock() 结束 protected 代码区域。

我列出的方法会自动生成一个 leave 指令,分支到 try 语句之后的第一条指令。我不想要这些,有两个原因。第一,因为它总是生成未优化的 leave 指令,而不是 leave.s 指令,即使它只是在两个字节之外进行分支。第二,因为您无法控制休假指令的去向。

所以,如果你想跳转到代码中的其他位置,你必须添加一个编译器生成的局部变量,根据你想在 try 语句中跳转到的位置设置它,让 EndExceptionBlock( ) 自动生成leave指令,然后在try block 下面生成switch语句。或者,您可以自己发出一条 leaveleave.s 指令,然后再调用之前的方法之一,导致丑陋且无法访问的额外 5 个字节,如下所示:

L_00ca: leave.s L_00e5
L_00cc: leave L_00d1

这两个选项对我来说都是 Not Acceptable 。有没有什么方法可以阻止 leave 指令的自动生成,或者有什么其他方法可以指定 protected 区域而不是使用这些方法(这些方法非常烦人而且几乎没有记录)?

编辑 注意:C# 编译器本身会执行此操作,因此似乎没有充分的理由将其强加给我们。例如,如果您有 .NET 4.5 beta,请反汇编以下代码并检查它们的实现:(内部添加的异常 block )

public static async Task<bool> TestAsync(int ms)
{
    var local = ms / 1000;
    Console.WriteLine("In async call, before await " + local.ToString() + "-second delay.");
    await System.Threading.Tasks.Task.Delay(ms);
    Console.WriteLine("In async call, after await " + local.ToString() + "-second delay.");

    Console.WriteLine();
    Console.WriteLine("Press any key to continue.");
    Console.ReadKey(false);
    return true;
}

最佳答案

据我所知,您不能在 .NET 4.0 中执行此操作。 不使用 ILGenerator 创建方法体的唯一方法是使用 MethodBuilder.CreateMethodBody,但这不允许您设置异常处理信息. ILGenerator 强制执行您询问的 leave 指令。

但是,如果 .NET 4.5 是您的一个选项(似乎是),请查看 MethodBuilder.SetMethodBody .这允许您自己创建 IL,但仍然传递异常处理信息。您可以将其包装在您自己的自定义 ILGenerator 类中,使用 Emit 方法采用 OpCode 参数,并读取 OpCode .SizeOpCode.Value 得到相应的字节。

当然还有 Mono.Cecil ,但这可能需要对您已编写的代码进行更广泛的更改。

编辑:you appear to have already figured this out yourself ,但您未解决这个问题。您可以张贴您自己的问题的答案并接受它们(如果您自己想出了答案)。这会让我知道我不应该浪费时间搜索,这会让其他有同样问题的人知道该怎么做。

关于c# - Reflection.Emit.ILGenerator异常处理 "Leave"指令,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9642512/

有关c# - Reflection.Emit.ILGenerator异常处理 "Leave"指令的更多相关文章

  1. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  2. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  3. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  4. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  5. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  6. ruby-on-rails - Rails - 乐观锁定总是触发 StaleObjectError 异常 - 2

    我正在学习Rails,并阅读了关于乐观锁的内容。我已将类型为integer的lock_version列添加到我的articles表中。但现在每当我第一次尝试更新记录时,我都会收到StaleObjectError异常。这是我的迁移:classAddLockVersionToArticle当我尝试通过Rails控制台更新文章时:article=Article.first=>#我这样做:article.title="newtitle"article.save我明白了:(0.3ms)begintransaction(0.3ms)UPDATE"articles"SET"title"='dwdwd

  7. ruby-on-rails - 相关表上的范围为 "WHERE ... LIKE" - 2

    我正在尝试从Postgresql表(table1)中获取数据,该表由另一个相关表(property)的字段(table2)过滤。在纯SQL中,我会这样编写查询:SELECT*FROMtable1JOINtable2USING(table2_id)WHEREtable2.propertyLIKE'query%'这工作正常:scope:my_scope,->(query){includes(:table2).where("table2.property":query)}但我真正需要的是使用LIKE运算符进行过滤,而不是严格相等。然而,这是行不通的:scope:my_scope,->(que

  8. 使用 ACL 调用 upload_file 时出现 Ruby S3 "Access Denied"错误 - 2

    我正在尝试编写一个将文件上传到AWS并公开该文件的Ruby脚本。我做了以下事情:s3=Aws::S3::Resource.new(credentials:Aws::Credentials.new(KEY,SECRET),region:'us-west-2')obj=s3.bucket('stg-db').object('key')obj.upload_file(filename)这似乎工作正常,除了该文件不是公开可用的,而且我无法获得它的公共(public)URL。但是当我登录到S3时,我可以正常查看我的文件。为了使其公开可用,我将最后一行更改为obj.upload_file(file

  9. ruby - #之间? Cooper 的 *Beginning Ruby* 中的错误或异常 - 2

    在Cooper的书BeginningRuby中,第166页有一个我无法重现的示例。classSongincludeComparableattr_accessor:lengthdef(other)@lengthother.lengthenddefinitialize(song_name,length)@song_name=song_name@length=lengthendenda=Song.new('Rockaroundtheclock',143)b=Song.new('BohemianRhapsody',544)c=Song.new('MinuteWaltz',60)a.betwee

  10. ruby - 安装 Ruby 时遇到问题(无法下载资源 "readline--patch") - 2

    当我尝试安装Ruby时遇到此错误。我试过查看this和this但无济于事➜~brewinstallrubyWarning:YouareusingOSX10.12.Wedonotprovidesupportforthispre-releaseversion.Youmayencounterbuildfailuresorotherbreakages.Pleasecreatepull-requestsinsteadoffilingissues.==>Installingdependenciesforruby:readline,libyaml,makedepend==>Installingrub

随机推荐