csharp中的小坑
最近重度使用csharp, 在写egraph中的图匹配, 简单记录一下遇到的一些小问题.
0x00 注意隐式转换与构造函数的冲突问题
因为cshapr每次都要写new,所以添加了一些隐式类型转换语法糖.
但是下面的代码就会出现问题,
就是new WildCardPattern(Name)
这里其实并不是调用默认的WildCardPattern(string Name, ExprPattern? Pattern)
,
而是又被隐式类型转换成了WildCardPattern
然后准备调用复制构造函数构造,但是隐式类型转换的时候就陷入递归了.
public sealed record WildCardPattern(string Name, ExprPattern? Pattern) : ExprPattern |
0x01 C# delegate的本质
最近在弄一个直接jit
生成代码然后用c#动态调用的东西,但是需要动态调用你必须要告诉当前的函数指针一个delegate
的定义,不然c#
就不知道你要输入什么返回什么.
那么既然是jit
,我们的就不能提前写好这个定义,
所以需要动态构造一个delegate
.
给定一个类: public class CustomType
{
public delegate float declf(float x, float y);
}delegate
的修饰符并不是一种attr
,而是一种表示他继承自MulticastDelegate
,
所以你可以发现他的是一个NestedType
,并且他的基类是MulticastDelegate
.
var t = cls_type.GetNestedType("declf");
Assert.Equal(t.BaseType, typeof(MulticastDelegate));
通过检查他的il
我们可以发现declf
就是个class
,所以事情就简化成了构造这个类的问题.:
.class private auto ansi '<Module>'
{
} // end of class <Module>
.class public auto ansi beforefieldinit CustomType
extends [mscorlib]System.Object
{
// Nested Types
.class nested public auto ansi sealed declf
extends [mscorlib]System.MulticastDelegate
{
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor (
object 'object',
native int 'method'
) runtime managed
{
} // end of method declf::.ctor
.method public hidebysig newslot virtual
instance float32 Invoke (
float32 x,
float32 y
) runtime managed
{
} // end of method declf::Invoke
.method public hidebysig newslot virtual
instance class [mscorlib]System.IAsyncResult BeginInvoke (
float32 x,
float32 y,
class [mscorlib]System.AsyncCallback callback,
object 'object'
) runtime managed
{
} // end of method declf::BeginInvoke
.method public hidebysig newslot virtual
instance float32 EndInvoke (
class [mscorlib]System.IAsyncResult result
) runtime managed
{
} // end of method declf::EndInvoke
} // end of class declf
// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x2050
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method CustomType::.ctor
} // end of class CustomTypebinding
那个dll
里面的函数,然后我们就可以动态的invoke
生成的代码了~
AssemblyName aName = new AssemblyName("DynamicAssemblyExample");
AssemblyBuilder ab = AssemblyBuilder.DefineDynamicAssembly(aName, AssemblyBuilderAccess.RunAndCollect);
ModuleBuilder mb = ab.DefineDynamicModule(aName.Name);
TypeBuilder tb = mb.DefineType("MyDynamicType", TypeAttributes.Public);
TypeBuilder nesttb = tb.DefineNestedType("DynamicDelegate", TypeAttributes.NestedPublic | TypeAttributes.Sealed, typeof(MulticastDelegate));
var ctor = nesttb.DefineConstructor(MethodAttributes.Public | MethodAttributes.HideBySig | MethodAttributes.SpecialName | MethodAttributes.RTSpecialName, CallingConventions.Standard | CallingConventions.HasThis, new[] { typeof(object), typeof(IntPtr) });
ILGenerator ctorIL = ctor.GetILGenerator();
ctorIL.Emit(OpCodes.Ldarg_0);
ctorIL.Emit(OpCodes.Ldarg_1);
ctorIL.Emit(OpCodes.Ret);
var invoke = nesttb.DefineMethod("Invoke", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot, CallingConventions.Standard | CallingConventions.HasThis, typeof(float), new[] { typeof(float), typeof(float) });
var beginInvoke = nesttb.DefineMethod("BeginInvoke", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot, CallingConventions.Standard | CallingConventions.HasThis, typeof(IAsyncResult), new[] { typeof(float), typeof(float), typeof(IAsyncResult), typeof(object) });
var endInvoke = nesttb.DefineMethod("EndInvoke", MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.NewSlot, CallingConventions.Standard | CallingConventions.HasThis, typeof(float), new[] { typeof(IAsyncResult) });
var created_class = tb.CreateType();
return created_class;
0x02 dotnet test crash时的解决方案
- 开启--blame以及--blame-crash
- 通过lldb+sos插件调试core dump.