这本来是一个更冗长的问题,但现在我构建了一个较小的可用示例代码,因此原始文本不再相关.
我有两个项目,一个包含一个没有成员的结构,名为TestType.该项目由主项目引用,但程序集不包含在可执行文件目录中.主项目创建一个新的app-domain,它使用所包含程序集的名称注册AssemblyResolve事件.在主app-domain中,处理相同的事件,但它手动从项目资源加载程序集.
然后新的app-domain构建自己的TestType版本,但字段多于原始字段.主app-domain使用虚拟版本,新app-domain使用生成的版本.
当调用 在其签名中具有TestType的方法时(即使只是简单地返回它就足够了),它似乎只会使运行时不稳定并破坏内存.
我使用的是.NET 4.5,在x86下运行.
DummyAssembly:
using System;
[Serializable]
public struct TestType
{
}
Run Code Online (Sandbox Code Playgroud)
主要项目:
using System;
using System.Reflection;
using System.Reflection.Emit;
internal sealed class Program
{
[STAThread]
private static void Main(string[] args)
{
Assembly assemblyCache = null;
AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs rargs)
{
var name = new AssemblyName(rargs.Name);
if(name.Name == "DummyAssembly")
{
return assemblyCache ?? (assemblyCache = TypeSupport.LoadDummyAssembly(name.Name));
}
return null; …Run Code Online (Sandbox Code Playgroud) 以下IL代码创建一个名为(fnptr)*(标记0x2000000 - 无效,模块mscorlib.dll)的Type实例.
ldtoken method void* ()*
call class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
Run Code Online (Sandbox Code Playgroud)
这种类型的目的是什么?是否可以在C#中创建此类型实例而无需编写任何IL代码,也许可以使用反射?令牌上的Module.ResolveType抛出ArgumentOutOfRangeException.
编辑:
很明显,(fnptr)类型是IL方法指针类型的内部CLR类型表示,但是当删除最后一个时*,它只是返回IntPtr.
编辑#2:
将(fnptr)来自可在可见的功能SSCLI typestring.cpp:
Run Code Online (Sandbox Code Playgroud)// ...or function pointer else if (ty.IsFnPtrType()) { // Don't attempt to format this currently, it may trigger GC due to fixups. tnb.AddName(L"(fnptr)"); }
为什么基本的fnptr返回IntPtr可以在typehandle.cpp中看到:
Run Code Online (Sandbox Code Playgroud)OBJECTREF TypeHandle::GetManagedClassObject() const {[...]
Run Code Online (Sandbox Code Playgroud)switch(GetInternalCorElementType()) { case ELEMENT_TYPE_ARRAY: case ELEMENT_TYPE_SZARRAY: case ELEMENT_TYPE_BYREF: case ELEMENT_TYPE_PTR: return ((ParamTypeDesc*)AsTypeDesc())->GetManagedClassObject(); …
我发现CIL compiller允许类型native float.但是,CLR不允许这样做.它有用吗?它的大小是多少?是否有相应的.NET类型?我试图将它实现为伪原始类型:
.class public sequential ansi serializable sealed beforefieldinit NativeFloat
extends System.ValueType
{
.field assembly native float m_value
}
Run Code Online (Sandbox Code Playgroud)
但是,CLR不支持此类型.谢谢您的帮助.
编辑:如果你有兴趣,它的CorElementType是26(0x1a,R).
有没有办法确定哪个AppDomain是对象或ObjectHandle实例创建的?
我需要在C中计算数字的日志基数2,但我不能使用数学库.答案不需要精确,只需要最接近的int.我已经考虑过了,我知道我可以使用while循环并继续将数字除以2,直到它<2,并保持迭代次数,但这是否可以使用按位运算符?
我在CIL中定义了一个字段,如下所示:
.field public int32 modopt(void*) fld
Run Code Online (Sandbox Code Playgroud)
我把它编译成一个程序集.现在我将其更改为:
.field public int32 modopt(int16) fld
Run Code Online (Sandbox Code Playgroud)
现在,ILDASM如何报告(当显示为十六进制时)这两个字段都是可能的?
Field #1 (04000001)
-------------------------------------------------------
Field Name: fld (04000001)
Flags : [Public] (00000006)
CallCnvntn: [FIELD]
Field type: CMOD_OPT 1b000001 I4
Signature : 06 20 06 08
Run Code Online (Sandbox Code Playgroud)
此代码查找两个字段完全相同(实际上我创建了第二个字段以匹配报告的签名).签名明显相匹配的第二场,但第一场的签名应该是这样的:06 20 0f 01 08!我在这里错过了什么?
编辑:
C#不能发出这种类型的字段,抛出关于自定义类型修饰符不支持的指针和数组类型的异常,因此这显然解决了签名不匹配问题.但是ILDASM允许创建无法反编译的无效签名的问题仍然存在.
编辑#2:
似乎ILASM实际上正在创建正确的IL,我上次错过的十六进制转储存在差异:
//the first assembly
TypeSpec #1 (1b000001)
-------------------------------------------------------
TypeSpec : Ptr Void
Signature: 0f 01
//the second assembly
TypeSpec #1 (1b000001)
-------------------------------------------------------
TypeSpec : I2
Signature: 06
Run Code Online (Sandbox Code Playgroud)
因此,ILDASM十六进制转储中只有一个错误报告了错误的成员签名(尽管我想知道06错误签名的来源).
我注意到正常的频道ID 在开始时有" UC ",而自动生成的频道有" HC ".普通播放列表具有" PL "但是特殊播放列表(如上传或喜欢的视频)具有" UU "和" FL ",但是它们不适用于自动生成的频道,它们具有" LP ".这就是我到目前为止所发现的.是否有所有这些前缀的列表及其含义?
编辑:基于特定视频的播放列表以" RD" +视频ID 开头.
我想我在Lua中看到了一个可以返回新用户数据的本地函数.它存在吗?是否可以从普通的Lua脚本创建自定义用户数据?
我有以下课程:
[StructLayout(LayoutKind.Sequential)]
class Class
{
public int Field1;
public byte Field2;
public short? Field3;
public bool Field4;
}
Run Code Online (Sandbox Code Playgroud)
如何Field4从类数据(或对象标题)的开头获取字节偏移量?
为了显示:
Class cls = new Class();
fixed(int* ptr1 = &cls.Field1) //first field
fixed(bool* ptr2 = &cls.Field4) //requested field
{
Console.WriteLine((byte*)ptr2-(byte*)ptr1);
}
Run Code Online (Sandbox Code Playgroud)
在这种情况下,结果偏移量为5,因为运行时实际上移动Field3到类型的末尾(并填充它),可能是因为它的类型是通用的.我知道有Marshal.OffsetOf,但它返回非托管偏移,不管理.
如何从FieldInfo实例中检索此偏移量?是否有任何.NET方法用于此,或者我是否必须编写自己的方法,考虑所有异常(类型大小,填充,显式偏移等)?
我知道GetFinalPathNameByHandle可用于获取符号链接或重分析点的目标,但在某些情况下不希望使用它:
似乎DeviceIoControl可以与 一起使用FSCTL_GET_REPARSE_POINT来获取文件的实际重新解析数据,但这让我得到了REPARSE_DATA_BUFFER,我必须解析它。
我不知道系统实际上如何处理重分析点,但我认为目标位置是一条应该在某个时刻可用的信息。dir例如,该命令可以正确显示任何重新分析点的目标路径...我已经看到它只处理符号链接和挂载点(连接点)。