我正在使用IL来抛出一个Int32并捕获它.这只是出于好奇,我不想做任何事情,所以请不要告诉我抛出异常而不是int.
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 40 (0x28)
.maxstack 2
.locals init (object V_0,
int32 V_1)
IL_0000: nop
.try
{
IL_0001: nop
IL_0002: ldsfld int32 ConsoleApplication3.Program::i
IL_0007: throw
} // end .try
catch [mscorlib]System.Object
{
IL_0008: stloc.0
IL_0009: nop
IL_000a: ldstr "In Object catch"
IL_000f: call void [mscorlib]System.Console::WriteLine(string)
IL_0014: nop
IL_0015: ldloc.0
IL_0016: unbox.any [mscorlib]System.Int32
IL_001b: stloc.1
IL_001c: ldloc.1
IL_001d: call void [mscorlib]System.Console::WriteLine(int32)
IL_0022: nop
IL_0023: nop
IL_0024: leave.s IL_0026
} …Run Code Online (Sandbox Code Playgroud) 标题实际上是要求所有,但为了完整起见:
嗨,我正在.NET平台上编写一个小的后编译工具,在尝试优化它时,我遇到了一个问题,我不能轻易找到ECMA标准的公共语言基础结构的答案(CLI).
单个类可以拥有的最大方法数是多少?有限制吗?
编辑:
感谢Kelsey指出真实的测试.虽然我仍然会关心实际限制是什么,但对于我的实际目的,我想知道它是否是2 ^ 16/2 ^ 32 - 或 - 2 ^ 31-1,正如他所指出的,它出现了显然高于每级64K方法..
我正在学习CLR中的托管和非托管代码.所以我用C#中的C风格指针编写了这个例子:
unsafe static void Main(string[] args)
{
int x;
int* y;
y = &x;
*y = 50;
Console.WriteLine(*y);
Console.WriteLine(((int)y).ToString());
}
Run Code Online (Sandbox Code Playgroud)
所以我想知道我从上面的代码得到的IL代码中真正不安全的是什么?
.assembly extern mscorlib
{}
.assembly UnsafePointers
{}
.module UnsafePointers.exe
.class private auto ansi beforefieldinit UnsafePointers.Program
extends [mscorlib]System.Object
{
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 34 (0x22)
.locals init (int32 x,
int32* y)
IL_0001: ldloca x
IL_0003: conv.u
IL_0004: stloc y
IL_0005: ldloc y
IL_0006: ldc.i4 50
IL_0008: stind.i4
IL_0009: ldloc y …Run Code Online (Sandbox Code Playgroud) TypedReference和ArgIterator?)?我怀疑它在编译器中是硬编码的,因为错误CS0610的文档指出:
有些类型不能用作字段或属性.这些类型包括......
在我看来哪些类型可以扩展 - 但我可能是错的.
我在SO上搜索了一下,虽然我明白以编程方式抛出编译器错误无法完成,但我找不到任何来源说明某些"特殊"类型的行为无法复制.
即使问题主要是学术问题,也可能会有一些答案.例如,有时可以确保某个对象的生命周期被约束到创建它的方法块.
编辑: RuntimeArgumentHandle是一种(未提及)不可存储的类型.
编辑2:如果它可以有任何用途,似乎CLR也以不同的方式处理这些类型,如果不仅仅是编译器(仍然假设类型与其他类型没有任何区别).例如,以下程序将提出一个TypeLoadException问题TypedReference*.我已经对它进行了调整以缩短它,但你可以随心所欲地解决它.例如,void*将指针的类型更改为不会抛出异常.
using System;
unsafe static class Program
{
static TypedReference* _tr;
static void Main(string[] args)
{
_tr = (TypedReference*) IntPtr.Zero;
}
}
Run Code Online (Sandbox Code Playgroud) 我有以下C#代码.
public void HelloWorld()
{
Add(2, 2);
}
public void Add(int a, int b)
{
//Do something
}
Run Code Online (Sandbox Code Playgroud)
它产生以下CIL
.method public hidebysig instance void HelloWorld() cil managed
{
// Code size 11 (0xb)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldc.i4.2
IL_0003: ldc.i4.2
IL_0004: call instance void ConsoleApplication3.Program::Add(int32,
int32)
IL_0009: nop
IL_000a: ret
} // end of method Program::HelloWorld
Run Code Online (Sandbox Code Playgroud)
现在,我不明白的是偏移0001处的线:
ldarg.0
我知道那个操作码的用途是什么,但我真的不明白为什么它在这个方法中使用,因为没有参数,对吧?
有人知道为什么吗?:)
我有一个OutOfMemoryException,我想分析应该创建的数组的大小和类型.
我为这种情况创建了一个演示目的转储,我能够获得以下信息:
0:000> !pe
Exception object: 023f389c
Exception type: System.OutOfMemoryException
Message: <none>
InnerException: <none>
StackTrace (generated):
SP IP Function
0015EE44 0099007F OOM2!OOM2.Program.Main()+0xf
StackTraceString: <none>
HResult: 8007000e
0:000> !u 0099007F
Normal JIT generated code
OOM2.Program.Main()
Begin 00990070, size 22
00990070 baffffff7f mov edx,7FFFFFFFh
00990075 b90241a478 mov ecx,offset mscorlib_ni+0x4102 (78a44102)
0099007a e8192194ff call 002d2198 (JitHelp: CORINFO_HELP_NEWARR_1_VC)
>>> 0099007f 8bc8 mov ecx,eax
...
Run Code Online (Sandbox Code Playgroud)
所以我可以看到创建了一个新数组,大小为7FFFFFFF,这是20亿个项目.(请忽略这样一个事实:您甚至无法在32位.NET应用程序中创建该大小的byte [],因此在此示例中类型可能根本不重要.)
我现在已经读过数组的类型在ECX寄存器中,但遗憾的mscorlib_ni+0x4102 (78a44102)是不是很有帮助.
我尝试过!mln,!mdt甚至不切实际!ip2mt,但没有一个显示预期byte或byte[]输出.有没有办法从mscorlib的原生图像中获取类型?
我试图在运行时使用反射创建方法的副本.
我有以下代码.
public static R CopyMethod<T, R>(Func<T, R> f, T t)
{
AppDomain currentDom = Thread.GetDomain();
AssemblyName asm = new AssemblyName();
asm.Name = "DynamicAssembly";
AssemblyBuilder abl = currentDom.DefineDynamicAssembly(asm, AssemblyBuilderAccess.Run);
ModuleBuilder mbl = abl.DefineDynamicModule("Module");
TypeBuilder tbl = mbl.DefineType("Type");
var info = f.GetMethodInfo();
MethodBuilder mtbl = tbl.DefineMethod(info.Name, info.Attributes, info.CallingConvention, info.ReturnType, info.GetParameters().Select(x => x.ParameterType).ToArray());
byte[] il = f.Method.GetMethodBody().GetILAsByteArray();
mtbl.CreateMethodBody(il, il.Length);
Type type = tbl.CreateType();
Func<T, R> method = type.GetMethod(info.Name).CreateDelegate(typeof(Func<T, R>)) as Func<T, R>;
return method(t);
}
Run Code Online (Sandbox Code Playgroud)
最后一行抛出一条带有消息的异常:
Common Language Runtime检测到无效程序.
还有另一种方法吗?我希望能够获得方法的解析树而不是直接使用IL.
编辑1: …
您是否知道有关CLR,.NET Framework和CIL的工作方式的任何好书,而不是任何特定的.NET语言?
在为我最喜欢的突变测试框架(NinjaTurtles)编写"Off By One"变异测试程序的过程中,我编写了以下代码,以便提供检查我的实现的正确性的机会:
public int SumTo(int max)
{
int sum = 0;
for (var i = 1; i <= max; i++)
{
sum += i;
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
现在这看起来很简单了,并没有让我觉得尝试改变IL中的所有文字整数常量会有问题.毕竟,只有3(the 0,the 1,and ++).
错误!
在第一次运行中它变得非常明显,它在这个特定的实例中永远不会起作用.为什么?因为将代码更改为
public int SumTo(int max)
{
int sum = 0;
for (var i = 0; i <= max; i++)
{
sum += i;
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
只在总和上加0(零),这显然没有效果.不同的故事,如果它是多组,但在这种情况下,它不是.
现在有一个相当简单的算法来计算整数之和
sum = max * (max + 1) / 2;
Run Code Online (Sandbox Code Playgroud)
我可以轻易地使突变失败,因为从任一常数中加1或减1会导致错误.(鉴于此max >= …
假设我有以下ILAsm代码:
.class public interface abstract ITest
{
.field public static int32 counter
.method public static void StaticMethod(string str)
{
ldarg.0
call void [mscorlib]System.Console::WriteLine(string)
ret
}
.method public virtual abstract void InstMethod(string) { }
}
Run Code Online (Sandbox Code Playgroud)
是否可以在C#中定义实现此ITest接口的类?
我可以在ILAsm中实现这个接口:
.class public TestImpl extends [mscorlib]System.Object implements ITest
{
.method public virtual void InstMethod(string str)
{
ldarg.1
call void ITest::StaticMethod(string)
ret
}
.method public specialname rtspecialname instance void .ctor()
{
ldarg.0
call instance void .base::.ctor()
ret
}
}
Run Code Online (Sandbox Code Playgroud)
并成功使用C#代码中实现的类:
var testImpl = new …Run Code Online (Sandbox Code Playgroud)