checking logic occur in MSIL or machine code

I've just started to dabble in the wonderful world of MSIL, but I can't seem to find any answers here about where bounds-checking occurs. Does the C# compiler insert MSIL instructions that perform bounds-checking, or does the MSIL JIT compiler insert them for all applicable MSIL instructions when translating those to machine code?

The reason I ask is because I need to know whether or not I need to add those instructions when I generate functions using MSIL directly.

EDIT: After receiving one answer and attempting to validate, it appears to be incorrect. The following code actually fails. Stepping through the debugger reveals that the second test writes beyond the array bounds, and the third test does much worse:

static class ArrayExtensions
{
#if false
    public static void ClearRangeReferenceImplementation(byte[] buffer, int offset, int byteCount)
    {
        for (int current = offset; current < offset + byteCount; ++current)
        {
            buffer[current] = 0;
        }
    }
#endif
    private static readonly Action<IntPtr, int, int> MemclearRaw = InitMemclearRaw();
    private static Action<IntPtr, int, int> InitMemclearRaw()
    {
        DynamicMethod memclearMethod = new DynamicMethod("Memclear", MethodAttributes.Public | MethodAttributes.Static, CallingConventions.Standard, null, new Type[] { typeof(IntPtr), typeof(int), typeof(int) }, typeof(this), true);
        ILGenerator il = memclearMethod.GetILGenerator();
        il.Emit(OpCodes.Ldarg_0);
        il.Emit(OpCodes.Ldarg_1);
        il.Emit(OpCodes.Add);
        il.Emit(OpCodes.Ldc_I4_0);
        il.Emit(OpCodes.Ldarg_2);
        il.Emit(OpCodes.Initblk);
        il.Emit(OpCodes.Ret);
        return (Action<IntPtr, int, int>)memclearMethod.CreateDelegate(typeof(Action<IntPtr, int, int>));
    }
    /// <summary>
    /// Clears the specified range of the specified buffer in the most optimal manner available without resorting to PInvoke or inline assembly.
    /// </summary>
    /// <param name="buffer">The buffer to acted upon.</param>
    /// <param name="offset">The offset in the buffer where the clearing is to start.</param>
    /// <param name="count">The number of bytes to be cleared.</param>
    public static void ClearRange(this byte[] buffer, int offset, int count)
    {
        if (count == 0) return;
        GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
        try
        {
            MemclearRaw(handle.AddrOfPinnedObject(), offset, count);
        }
        finally
        {
            handle.Free();
        }
    }
}
[TestClass]
public class TestArrayExtensions
{
    /// <summary>
    /// Performs failure tests on <see cref="ArrayExtensions.ClearRange"/>.
    /// </summary>
    [TestMethod]
    public void Array_ClearRangeExceptions()
    {
        byte[] b = Rand.NewBytes(0, 100);
        AssertExceptionClearRange(null, 0, b.Length, typeof(NullReferenceException));
        b = Rand.NewBytes(0, 100);
        AssertExceptionClearRange(b, 0, b.Length + 1, typeof(ArgumentOutOfRangeException));
        b = Rand.NewBytes(0, 100);
        AssertExceptionClearRange(b, 0, -1, typeof(ArgumentOutOfRangeException));
        b = Rand.NewBytes(0, 100);
        AssertExceptionClearRange(b, -1, b.Length, typeof(ArgumentOutOfRangeException));
    }

    private static void AssertExceptionClearRange(byte[] buffer, int offset, int count, Type exceptionType)
    {
        try
        {
            ArrayExtensions.ClearRange(buffer, offset, count);
            Assert.Fail("ArrayExtensions.ClearRange did not throw the expected exception!");
        }
        catch (Exception ex)
        {
            Assert.AreEqual(exceptionType, ex.GetType());
        }
    }

It appears that the MSIL only does null pointer checking, NOT bounds checking.

I'm currently using VS2012 and targeting .NET Framework 4.5.1 if that makes any difference.


The C# compiler does very little optimization.

All the magic happens in the JIT which generates the machine code.

To answer the question, if you generate similar code to what C# or VB.NET does (iow the JIT can determine this is some form of for loop, etc), it will work.

链接地址: http://www.djcxy.com/p/36070.html

上一篇: 获取本地IP地址

下一篇: 检查逻辑发生在MSIL或机器代码中