You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Peverify和ILVerify验证不安全C#返回类型时出现验证错误

为什么我的Unsafe C#代码能编译运行却通不过ILVerify/Peverify验证?

首先得明确一个核心点:IL验证器(Peverify/ILVerify)是为类型安全的托管代码设计的,而unsafe代码本身就是用来突破CLR的类型安全约束的——所以这类代码本质上就不符合验证器的规则,通不过验证是意料之中的事。

接下来咱们拆解你遇到的两个错误,以及背后的深层原因:

1. A::GetAnswer()的验证错误

错误信息:[IL]: Error: [C:\src\test\example.dll : A::GetAnswer()][offset 0x00000006][found address of Int32] Expected numeric type on the stack.

你的GetAnswer方法返回了局部变量fakeValue的指针,编译器生成的IL逻辑大致是:

  • 将42存入局部变量fakeValue
  • 通过ldloca.s指令获取fakeValue的地址(得到byref类型的值)
  • 用conv.i指令把这个地址转换为原生整数(对应C#里的int*指针)
  • 返回这个值

但CLR的类型安全规则严格禁止返回局部变量的地址:局部变量存储在方法的栈帧中,方法执行完毕后栈帧会被销毁,对应的内存会被回收或覆盖,返回这个地址会产生野指针,属于严重的类型安全违规。IL验证器检测到了这个违规,所以报错——它期望栈上是符合返回类型的数值类型(原生整数),但实际看到的是局部变量的byref地址,认为这个操作不符合类型安全规范。

2. A::Main()的验证错误

错误信息:[IL]: Error: [C:\src\test\example.dll : A::Main()][offset 0x00000009][found Native Int] Expected ByRef on the stack.

在Main方法中,你解引用了GetAnswer返回的指针,对应的IL逻辑是调用GetAnswer得到原生整数(指针),然后用ldind.i4指令解引用它。但在类型安全的托管代码中,解引用操作只能针对byref类型(托管引用),而不能直接针对原生指针。IL验证器遵循类型安全规则,所以当它看到栈上是原生整数(指针)时,就报错说期望ByRef类型,而不是原生指针。

额外提醒:你的代码存在未定义行为

虽然这段代码在你的测试中能编译运行并输出42,但这只是巧合——fakeValue是栈上的局部变量,GetAnswer返回后,它的内存已经不再属于有效范围,解引用这个指针可能会得到随机垃圾值,甚至导致程序崩溃,这属于C#中的未定义行为,绝对不能在生产代码中使用。

内容的提问来源于stack exchange,提问作者miniwolf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:57:33