是否有VS插件或独立应用程序形式的IL级调试器?
Visual Studio的调试器很棒,但它允许您在HLL代码级别或汇编语言上进行调试,您无法调试IL.在某些情况下,似乎有机会在IL级别进行调试.
特别是在调试代码中没有源代码的问题时可能会有所帮助.
如果在没有源的情况下调试IL实际上是有用的,那么这是有争议的,但无论如何.
有没有人知道比较两个.NET程序集以确定它们是否是从"相同"源文件构建的方法?
我知道有一些差异实用程序可用,例如Reflector的插件,但我对查看GUI中的差异不感兴趣,我只是想要一种自动方式来比较二进制文件的集合,看看它们是否是从相同(或等效)的源文件.我知道多个不同的源文件可以产生相同的IL,并且意识到该过程只对IL的差异敏感,而不是原始源.
仅仅比较两个程序集的字节流的主要障碍是.NET包含一个名为"MVID"(模块版本标识符)的程序集.这似乎对每个编译都有不同的值,因此如果您构建相同的代码两次,则程序集将有所不同.
一个相关的问题是,是否有人知道如何强制MVID为每个编译相同?这将避免我们需要具有对MVID值的差异不敏感的比较过程.一致的MVID将是更可取的,因为这意味着可以使用标准校验和.
这背后的背景是,在我们被允许发布到Production之前,第三方公司负责独立审核和签署我们的版本.这包括查看源代码.他们希望独立确认我们提供的源代码与我们之前构建,测试并且当前计划部署的二进制文件相匹配.我们正在寻找一个允许它们从我们提供的源中独立构建系统的过程,并将校验和与我们测试的二进制文件的校验和进行比较.
BTW.请注意,我们正在使用持续集成,自动构建,源代码控制等.该问题与内部缺乏对源文件进入给定构建的控制无关.问题在于,第三方负责验证我们提供的来源是否与我们测试过并计划投入生产的二进制文件相同.他们不应该信任我们的任何内部系统或控件,包括构建服务器或源代码控制系统.他们所关心的只是获取与构建相关的源,自己执行构建,并验证输出是否与我们所说的部署相匹配.
比较解决方案的运行速度并不是特别重要.
谢谢
我很想知道为什么会这样.请阅读下面的代码示例以及每个部分下面的注释中发出的相应IL:
using System;
class Program
{
static void Main()
{
Object o = new Object();
o.GetType();
// L_0001: newobj instance void [mscorlib]System.Object::.ctor()
// L_0006: stloc.0
// L_0007: ldloc.0
// L_0008: callvirt instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
new Object().GetType();
// L_000e: newobj instance void [mscorlib]System.Object::.ctor()
// L_0013: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType()
}
}
Run Code Online (Sandbox Code Playgroud)
为什么编译器callvirt为第一部分发出a 而call第二部分发出a ?是否有任何理由编译器会发出callvirt非虚方法的指令?如果在某些情况下编译器将callvirt为非虚拟方法发出一个,这会产生类型安全问题吗?
背景:
我想static在C#中定义几个方法,并从运行时(在客户端)选择的这些方法之一生成IL代码作为字节数组,并通过网络将字节数组发送到另一台机器(服务器),之后应该执行它从字节数组重新生成IL代码.
我的尝试:(POC)
public static class Experiment
{
public static int Multiply(int a, int b)
{
Console.WriteLine("Arguments ({0}, {1})", a, b);
return a * b;
}
}
Run Code Online (Sandbox Code Playgroud)
然后我得到方法体的IL代码,如:
BindingFlags flags = BindingFlags.Public | BindingFlags.Static;
MethodInfo meth = typeof(Experiment).GetMethod("Multiply", flags);
byte[] il = meth.GetMethodBody().GetILAsByteArray();
Run Code Online (Sandbox Code Playgroud)
到目前为止,我没有动态创建任何东西.但是我把IL代码作为字节数组,我想创建一个程序集,然后是一个模块,然后是一个类型,然后是一个方法 - 所有这些都是动态的.在创建动态创建方法的方法体时,我使用上面代码中使用反射得到的IL代码.
代码生成代码如下:
AppDomain domain = AppDomain.CurrentDomain;
AssemblyName aname = new AssemblyName("MyDLL");
AssemblyBuilder assemBuilder = domain.DefineDynamicAssembly(
aname,
AssemblyBuilderAccess.Run);
ModuleBuilder modBuilder = assemBuilder.DefineDynamicModule("MainModule");
TypeBuilder tb = modBuilder.DefineType("MyType",
TypeAttributes.Public | TypeAttributes.Class);
MethodBuilder mb …Run Code Online (Sandbox Code Playgroud) Daniel在他的回答中指出(除非我读错了)ECMA-335 CLI规范允许编译器生成抛出NullReferenceException以下DoCallback方法的代码.
class MyClass {
private Action _Callback;
public Action Callback {
get { return _Callback; }
set { _Callback = value; }
}
public void DoCallback() {
Action local;
local = Callback;
if (local == null)
local = new Action(() => { });
local();
}
}
Run Code Online (Sandbox Code Playgroud)
他说,为了保证NullReferenceException不抛出,volatile关键字应该用于_Callback或lock应该在线周围使用local = Callback;.
有人可以证实这一点吗?而且,如果确实如此,Mono和.NET编译器之间在这个问题上的行为是否存在差异?
编辑
这是标准的链接. …
.NET c#编译器(.NET 4.0)fixed以一种相当特殊的方式编译语句.
这是一个简短但完整的程序,向您展示我在说什么.
using System;
public static class FixedExample {
public static void Main() {
byte [] nonempty = new byte[1] {42};
byte [] empty = new byte[0];
Good(nonempty);
Bad(nonempty);
try {
Good(empty);
} catch (Exception e){
Console.WriteLine(e.ToString());
/* continue with next example */
}
Console.WriteLine();
try {
Bad(empty);
} catch (Exception e){
Console.WriteLine(e.ToString());
/* continue with next example */
}
}
public static void Good(byte[] buffer) {
unsafe {
fixed (byte * p = &buffer[0]) { …Run Code Online (Sandbox Code Playgroud) 该System.Threading.Interlocked对象允许加法(减法)和比较作为原子操作.似乎只是不做相等的CompareExchange以及作为原子比较的GreaterThan/LessThan将是非常有价值的.
Interlocked.GreaterThanIL 的假设特征还是CPU级功能?都?
缺少任何其他选项,是否可以用C++或直接IL代码创建这样的功能并将该功能公开给C#?
我正在浏览我的一个程序集的某些IL(通过ILDasm),我注意到我的所有方法都以一条 指令开头nop .
有谁知道那是为什么?
由于这个问题是关于增量运算符和带前缀/后缀表示法的速度差异,我将非常仔细地描述这个问题,以免Eric Lippert发现它并激怒我!
(有关我为什么要问的更多信息和详细信息,请访问http://www.codeproject.com/KB/cs/FastLessCSharpIteration.aspx?msg=3899456#xx3899456xx/)
我有四个代码片段如下: -
(1)单独,前缀:
for (var j = 0; j != jmax;) { total += intArray[j]; ++j; }
Run Code Online (Sandbox Code Playgroud)
(2)单独,后缀:
for (var j = 0; j != jmax;) { total += intArray[j]; j++; }
Run Code Online (Sandbox Code Playgroud)
(3)Indexer,Postfix:
for (var j = 0; j != jmax;) { total += intArray[j++]; }
Run Code Online (Sandbox Code Playgroud)
(4)索引器,前缀:
for (var j = -1; j != last;) { total += intArray[++j]; } // last = jmax - 1
Run Code Online (Sandbox Code Playgroud)
我试图做的是证明/反驳在这个上下文中前缀和后缀表示法之间是否存在性能差异(即局部变量因此不易变,不能从另一个线程等变化)如果存在,为什么会出现这种情况.
速度测试表明:
(1)和(2)以相同的速度运行.
(3)和(4)以相同的速度运行.
(3)/(4)比(1)/(2)慢〜27%.
因此,我得出的结论是,在postfix表示法本身上选择前缀表示法没有性能优势.但是,当实际使用操作的结果 …
由于这些IL代码我所看到的更多,我喜欢学习如何正确解释它们.
我找不到像C#Compiler或其他任何文档这样的文档,所以我想在学习了这些常见的文档之后我几乎可以完成其余的工作:
以下是一些包含我需要知道的IL代码示例:
样本1:
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
// Code size 15 (0xf)
.maxstack 1
.locals init ([0] class EnumReflection.DerivedClass derivedClass)
IL_0000: nop
IL_0001: newobj instance void EnumReflection.DerivedClass::.ctor()
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: callvirt instance void EnumReflection.DerivedClass::WriteOutput()
IL_000d: nop
IL_000e: ret
} // end of method Program::Main
Run Code Online (Sandbox Code Playgroud)
样本2:
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 38 (0x26)
.maxstack 8
IL_0000: ldarg.0
IL_0001: ldstr "Hello"
IL_0006: stfld …Run Code Online (Sandbox Code Playgroud) il ×10
.net ×6
c# ×6
assemblies ×1
c++ ×1
checksum ×1
cil ×1
clr ×1
debugging ×1
interlocked ×1
nop ×1
optimization ×1
performance ×1
reflection ×1
type-safety ×1