none
MemoryStream反编译代码为何不超过索引? RRS feed

  • 问题

  • 为了更好地了解MemoryStream的原理,我使用最新的Reflector反编译查看Write方法,其中关键如下:

    [SecuritySafeCritical]

    public override void Write(byte[] buffer, int offset, int count)

    {

      ………………………… //此处省略

        int num = this._position + count;

        if (num < 0)

        {

            throw new IOException(Environment.GetResourceString("IO.IO_StreamTooLong"));

        }

        if (num > this._length)

        {

            bool flag = this._position > this._length;

            if ((num > this._capacity) && this.EnsureCapacity(num))

            {

                flag = false;

            }

            if (flag)

            {

                Array.Clear(this._buffer, this._length, num - this._length);

            }

            this._length = num;

        }

        if ((count <= 8) && (buffer != this._buffer))     //第一问:为什么要判断count<=8?

        {

            int num2 = count;

            while (--num2 >= 0)

            {

                this._buffer[this._position + num2] = buffer[offset + num2];

                //第二问(注意我下面的问题和代码)——

            }

        }

        else

        {

            Buffer.InternalBlockCopy(buffer, offset, this._buffer, this._position, count);

        }

        this._position = num;

    }

    【第二问】

    现在假设我这样调用代码:

    byte[] bytes = new byte[8];
    MemoryStream ms = new MemoryStream(bytes,0,bytes.Length,true,true);
    ms.Write(new byte[] { 123 }, 12);

    那么执行到粗体部分的“第二问”的时候offset=1,count=2。那么buffer[3],这里的buffer既然是new byte[]{1,2,3}……为什么没有出现溢出错误呢?明明总数只有3个,因此最大的索引应该是2啊?

    请教了!谢谢!

    2012年1月31日 6:02

答案

  • 首先,//第一问:为什么要判断count<=8 我个人认为8 byte在内存中代表着十分重要的东西,比如说内存地址。Byte通常作为计算机的信息计量单位,但是这里用8可能是出于性能的考虑和设计的需要,因为从代码上看,当要向内存中写入的byte数小于等于8的时候,是一个byte一个byte写入内存的。 当大于8时, 该方法调用的是其他方法——InternalBlockCopy,这个方法的原型是C++代码,也是处理内存写入的。

    然后是第二问,我觉得您应该首先明白的是count代表的是什么意思。MSDN文档上说的是count代表最多写入的字节数。MemoryStream.Write 方法 (System.IO) 也就是说当您设置为2,offset偏移量为1的时候,不管您的buffer是多长,只会向内存中写入前2byte,也就是buffer[0]buffer[1].

    分析一下代码:虽然buffer的长度是3 但是在执行到

                   

      int num2 = count;
     //以下循环一共执行2次。
            while (--num2 >= 0)//首先num2先减1,
     
            {
     
                this._buffer[this._position + num2] = buffer[offset + num2];//第一次循环,offset=1,num2 =1, 第二次循环,offset=1,num2 =0.
     
            }
     
        }
    
    

     

    的时候,num2 = 2, 但是到第一次while循环里,buffer[offset =1+ 1]其实是buffer[2],我想您指的索引应该是说count2,可能您需要详细的参考一下MSDN文档。

     

    希望以上的内容对您有所帮助。

     


    Best Regards,
    Rocky Yue[MSFT]
    MSDN Community Support | Feedback to us

    2012年2月1日 7:19
    版主
  • 它可能就是这样设计的,因为执行的是--操作,第一次copy的是buffer[2],下一次就是copy buffer[1]了。其实写入哪一项,跟offset偏移量也是有关系的。
    Best Regards,
    Rocky Yue[MSFT]
    MSDN Community Support | Feedback to us
    • 已标记为答案 TimoYang 2012年3月4日 3:55
    2012年2月1日 7:50
    版主

全部回复

  • 首先,//第一问:为什么要判断count<=8 我个人认为8 byte在内存中代表着十分重要的东西,比如说内存地址。Byte通常作为计算机的信息计量单位,但是这里用8可能是出于性能的考虑和设计的需要,因为从代码上看,当要向内存中写入的byte数小于等于8的时候,是一个byte一个byte写入内存的。 当大于8时, 该方法调用的是其他方法——InternalBlockCopy,这个方法的原型是C++代码,也是处理内存写入的。

    然后是第二问,我觉得您应该首先明白的是count代表的是什么意思。MSDN文档上说的是count代表最多写入的字节数。MemoryStream.Write 方法 (System.IO) 也就是说当您设置为2,offset偏移量为1的时候,不管您的buffer是多长,只会向内存中写入前2byte,也就是buffer[0]buffer[1].

    分析一下代码:虽然buffer的长度是3 但是在执行到

                   

      int num2 = count;
     //以下循环一共执行2次。
            while (--num2 >= 0)//首先num2先减1,
     
            {
     
                this._buffer[this._position + num2] = buffer[offset + num2];//第一次循环,offset=1,num2 =1, 第二次循环,offset=1,num2 =0.
     
            }
     
        }
    
    

     

    的时候,num2 = 2, 但是到第一次while循环里,buffer[offset =1+ 1]其实是buffer[2],我想您指的索引应该是说count2,可能您需要详细的参考一下MSDN文档。

     

    希望以上的内容对您有所帮助。

     


    Best Regards,
    Rocky Yue[MSFT]
    MSDN Community Support | Feedback to us

    2012年2月1日 7:19
    版主
  • 谢谢回答!

    不过这样还有一个问题:

    position应该是指向MemoryStream内部的一个指针,初始化为0;那么当上面的while执行的时候,第一次this._buffer[0+1]=buffer[2],不是从0开始(第一个字节拷贝的)?

    谢谢!

    • 已标记为答案 TimoYang 2012年3月4日 3:55
    • 取消答案标记 TimoYang 2012年3月4日 3:55
    2012年2月1日 7:44
  • 它可能就是这样设计的,因为执行的是--操作,第一次copy的是buffer[2],下一次就是copy buffer[1]了。其实写入哪一项,跟offset偏移量也是有关系的。
    Best Regards,
    Rocky Yue[MSFT]
    MSDN Community Support | Feedback to us
    • 已标记为答案 TimoYang 2012年3月4日 3:55
    2012年2月1日 7:50
    版主