[英]struct/value type memory allocation and deacllocation
最近,我阅读了Jon Skeet的Blog,该博客讨论C#对象的占用空间和开销。 我编写了以下代码来复制他的实验。
class Pixel
{
private byte _r;
private byte _g;
private byte _b;
public int x { get; set; }
public int y { get; set; }
public System.Windows.Media.Color Color
{
get { return System.Windows.Media.Color.FromRgb(_r, _g, _b); }
}
}
static void Main(string[] args)
{
size = 1000;
var array3 = new Pixelsize];
before = GC.GetTotalMemory(true);
for (int i = 0; i < size; i++)
{
array3[i] = new Pixel();
}
after = GC.GetTotalMemory(true);
Console.WriteLine("Pixel is {0} bytes", (after - before) / size);
}
到目前为止,程序报告"Pixel is 15 bytes"
,即8字节基础+ 4字节+1 + 1 +1 = 15字节。
然后我想知道: struct
实例的开销与class
实例的开销相同吗? 因此,我将Pixel
更改为struct
。
struct Pixel
{
private byte _r;
private byte _g;
private byte _b;
public int x { get; set; }
public int y { get; set; }
public System.Windows.Media.Color Color
{
get { return System.Windows.Media.Color.FromRgb(_r, _g, _b); }
}
}
现在,程序报告"Pixel is 0 bytes"
。 进入代码,我发现after
与before
相同。 因此struct是一个值类型,它是从堆栈中分配的。 对? 例外,当我检查寄存器时,“ ESP
”完全没有变化。 所以它不是从堆栈分配的?
查看TaskManager后,分配后演示程序的内存使用量增加了8000个字节。 这8000个字节来自哪里?
最后,由于GC尚未注意内存分配,我该如何释放该内存? 我试图将分配代码放在一个块中,并希望当array3超出范围时,这些内存将被释放。 但是,内存使用情况没有改变。 我在这里发生内存泄漏吗?
static void Main(string[] args)
{
{
size = 1000;
var array3 = new Pixelsize];
before = GC.GetTotalMemory(true);
for (int i = 0; i < size; i++)
{
array3[i] = new Pixel();
}
after = GC.GetTotalMemory(true);
Console.WriteLine("Pixel is {0} bytes", (after - before) / size);
}
//Expect the memory to be released here, but nothing happened.
}
当分配引用类型的Array
时,在函数内部。对数组本身的引用可以存储在预分配的堆栈帧中(即4/8字节表示32/64位)。 1000个元素的实际分配在堆上 ,每个元素又分配 4/8个字节。 此外,您调用new Pixel()
会分配class的实例,并且由于它们的引用已存储在数组中而保持活动。
当您将其更改为函数内部的值类型Array
时。对数组本身的引用可能存储在预分配的堆栈帧中(即对于32/64位为4/8字节)。 1000个元素的实际分配在堆上 ,每个元素x个字节的大小,其中x是值类型的大小。 分配给数组元素的任何值都会在每个字节中被复制。 数组元素未引用任何内容。
由于您分配了值类型数组,因此在调用before = GC.GetTotalMemory(true);
,之前和之后的分配没有任何区别。
换句话说,在类的情况下,分配位于行array3[i] = new Pixel();
(在堆上),但在使用sruct的情况下,分配位于行var array3 = new Pixel[size];
对于结构, new Pixel();
在堆栈上使用了很少的空间,但是随后将该值复制到堆中数组的预分配空间中……并且很可能在每次迭代中都重复使用该堆栈空间。
如果考虑int
数组而不是Pixel
数组,则可能更容易考虑整个问题。除了它们的大小不同之外, int
和Pixel
(定义为struct)之间的机制相同。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.