首先早晨仔细复习了下delphi中栈的大小,delphi里默认栈的大小是1M多,函数中的静态数组是存在栈中的,动态数组都是存在堆中的,于是好奇之下用C#做了个实验 void teststack(byte [] b,int filesize)
        {
            FileStream fw = new FileStream(@"D:\aaback.zip", FileMode.Create);
            fw.Write(b, 0, filesize);
            fw.Flush();
            fw.Close();
        }        private void button1_Click(object sender, EventArgs e)
        {
            byte[] b=new byte[8738129];
            FileStream f = new FileStream(@"D:\aa.zip",FileMode.Open);
            int filesize=(int)f.Seek(0,SeekOrigin.End);
            f.Seek(0,SeekOrigin.Begin);
            f.Read(b, 0, filesize);
            f.Close();
            teststack(b, filesize);
            MessageBox.Show("finish");
        }测试结果是生成的文件一切正常,程序也没有报错
那请问一下,C#里默认栈的大小是多大呢?我用的是64位win7系统,c#2010
顺便再小问一下,今天查到论坛有个人提过类似的问题,居然有人回答C#默认栈大小是2G,还有人说栈的大小和操作系统有关,这些说法对么?
本帖是很认真地求职贴,如果不确定的童鞋请不要随意回答啊

解决方案 »

  1.   

    这篇文章可以仔细的看看http://stackoverflow.com/questions/1113819/c-arrays-heap-and-stack-and-value-types虽然int[]这里的值存在heap中,但是
    intarray[0] = 10;
    int a = intarray[1]
    这样的操作并不会box和unbox.
      

  2.   

    不会吧Stackoverflow居然打不开。问题:
    int[] myIntegers;
    myIntegers = new int[100];
    In the above code, is new int[100] generating the array on the heap? From what I've read on CLR via c#, the answer is yes. But what I can't understand, is what happens to the actual int's inside the array. As they are value types, I'd guess they'd have to be boxed, as I can, for example, pass myIntegers to other parts of the program and it'd clutter up the stack if they were left on it all the time. Or am I wrong? I'd guess they'd just be boxed and would live on the heap for as long the array existed.
      

  3.   

    最热的回答Your array is allocated on the heap, and the ints are not boxed.The source of your confusion is likely because people have said that reference types are allocated on the heap and value types are allocated on the stack. This is not an entirely accurate representation.All local variables and parameters are allocated on the stack. This includes both value types and reference types. The difference between the two is only what is stored in the variable. Unsurprisingly, for a value type, the value of the type is stored directly in the variable, and for a reference type, the value of the type is stored on the heap, and a reference to this value is what is stored in the variable.The same holds true for fields. When memory is allocated for an instance of an aggregate type (a class or a struct), it must include storage for each of its instance fields. For reference-type fields, this storage holds just a reference to the value, which would itself be allocated on the heap later. For value-type fields, this storage holds the actual value.So, given the following types:class RefType{
        public int    I;
        public string S;
        public long   L;
    }struct ValType{
        public int    I;
        public string S;
        public long   L;
    }
    The values of each of these types would require 16 bytes of memory (assuming a 32-bit word size). The field I in each case takes 4 bytes to store its value, the field S takes 4 bytes to store its reference, and the field L takes 8 bytes to store its value. So the memory for the value of both RefType and ValType looks like this: 0 ┌───────────────────┐
       │        I          │
     4 ├───────────────────┤
       │        S          │
     8 ├───────────────────┤
       │        L          │
       │                   │
    16 └───────────────────┘
    Now if you had three local variables in a function, of types RefType, ValType, and int[], like this:RefType refType;
    ValType valType;
    int[]   intArray;
    then your stack might look like this: 0 ┌───────────────────┐
       │     refType       │
     4 ├───────────────────┤
       │     valType       │
       │                   │
       │                   │
       │                   │
    20 ├───────────────────┤
       │     intArray      │
    24 └───────────────────┘
    If you assigned values to these local variables, like so:refType = new RefType();
    refType.I = 100;
    refType.S = "refType.S";
    refType.L = 0x0123456789ABCDEF;valType = new ValType();
    valType.I = 200;
    valType.S = "valType.S";
    valType.L = 0x0011223344556677;intArray = new int[4];
    intArray[0] = 300;
    intArray[1] = 301;
    intArray[2] = 302;
    intArray[3] = 303;
    Then your stack might look something like this: 0 ┌───────────────────┐
       │    0x4A963B68     │ -- heap address of `refType`
     4 ├───────────────────┤
       │       200         │ -- value of `valType.I`
       │    0x4A984C10     │ -- heap address of `valType.S`
       │    0x44556677     │ -- low 32-bits of `valType.L`
       │    0x00112233     │ -- high 32-bits of `valType.L`
    20 ├───────────────────┤
       │    0x4AA4C288     │ -- heap address of `intArray`
    24 └───────────────────┘
    Memory at address 0x4A963B68 (value of refType) would be something like: 0 ┌───────────────────┐
       │       100         │ -- value of `refType.I`
     4 ├───────────────────┤
       │    0x4A984D88     │ -- heap address of `refType.S`
     8 ├───────────────────┤
       │    0x89ABCDEF     │ -- low 32-bits of `refType.L`
       │    0x01234567     │ -- high 32-bits of `refType.L`
    16 └───────────────────┘
    Memory at address 0x4AA4C288 (value of intArray) would be something like: 0 ┌───────────────────┐
       │        4          │ -- length of array
     4 ├───────────────────┤
       │       300         │ -- `intArray[0]`
     8 ├───────────────────┤
       │       301         │ -- `intArray[1]`
    12 ├───────────────────┤
       │       302         │ -- `intArray[2]`
    16 ├───────────────────┤
       │       303         │ -- `intArray[3]`
    20 └───────────────────┘
    Now if you passed intArray to another function, the value pushed onto the stack would be 0x4AA4C288, the address of the array, not a copy of the array.
      

  4.   

    次热的回答Yes the array will be located on the heap.The ints inside the array will not be boxed. Just because a value type exists on the heap, does not necessarily mean it will be boxed. Boxing will only occur when a value type, such as int, is assigned to a reference of type object.For exampleDoes not box:int i = 42;
    myIntegers[0] = 42;
    Boxes:object i = 42;
    object[] arr = new object[10];  // no boxing here 
    arr[0] = 42;
    You may also want to check out Eric's post on this subject:http://blogs.msdn.com/ericlippert/archive/2009/05/04/the-stack-is-an-implementation-detail-part-two.aspx
      

  5.   

    本帖最后由 caozhy 于 2011-07-22 14:27:19 编辑
      

  6.   

    2GB 是 32bit Windows 桌面操作系统用户可分配内存地址的上限。
      

  7.   

    固定数组在函数体内分配是在栈中的
     我们做一个试验,一般DELPHI程序线程的栈大小是1M,如果我们函数体中申请4M大小的数组,报栈溢出,则表示数据的大小是在栈中的。
    const
     CArrayCount = 1024*1024*4;
     
    procedure TForm1.btnMainThreadClick(Sender: TObject);
     var
     MainThreadArray: array[1..CArrayCount] of Char;
     i: Integer;
     begin
     for i := Low(MainThreadArray) to High(MainThreadArray) do
         MainThreadArray[i] := #0;
     end;
     
    我把以上代码在主线程中测试时,确实报了栈溢出,如果这时你把DELPHI程序的栈调大为6M则正确,表示在函数体中申请的数组是在栈中的。
    而以下是我在C#中测试的代码则顺利通过
            const int CArrayCount = 1024*1024*4;
            private void button2_Click(object sender, EventArgs e)
            {
                char[] b = new char[CArrayCount];
                for (int i = 0; i < CArrayCount; i++)
                {
                    b[i] = (char)0;
                }            MessageBox.Show("finish");
            }
    总结:c#和delphi对于栈的存储采取不同的处理方式吧~
      

  8.   

    固定数组在函数体内分配是在栈中的
     我们做一个试验,一般DELPHI程序线程的栈大小是1M,如果我们函数体中申请4M大小的数组,报栈溢出,则表示数据的大小是在栈中的。
    const
     CArrayCount = 1024*1024*4;
     
    procedure TForm1.btnMainThreadClick(Sender: TObject);
     var
     MainThreadArray: array[1..CArrayCount] of Char;
     i: Integer;
     begin
     for i := Low(MainThreadArray) to High(MainThreadArray) do
         MainThreadArray[i] := #0;
     end;
     
    我把以上代码在主线程中测试时,确实报了栈溢出,如果这时你把DELPHI程序的栈调大为6M则正确,表示在函数体中申请的数组是在栈中的。
    而以下是我在C#中测试的代码则顺利通过
            const int CArrayCount = 1024*1024*4;
            private void button2_Click(object sender, EventArgs e)
            {
                char[] b = new char[CArrayCount];
                for (int i = 0; i < CArrayCount; i++)
                {
                    b[i] = (char)0;
                }            MessageBox.Show("finish");
            }
    总结:c#和delphi对于栈的存储采取不同的处理方式吧~