c# 啥时候在栈上分配数组?

Posted

技术标签:

【中文标题】c# 啥时候在栈上分配数组?【英文标题】:When is array allocated on stack in c#?c# 什么时候在栈上分配数组? 【发布时间】:2015-11-23 07:05:28 【问题描述】:

我一直试图弄清楚什么时候在堆栈上分配了东西,但我不知道如何让数组(或者更确切地说是其中的值)在堆栈上分配;

在这个例子中:

public void foo()

    int bar[] = new int [10];

10 个 int 结构将分配在堆上,只有指向它们的指针会在堆栈上,对吗?

如何将固定大小的数组放入堆栈?如果我使用我定义的结构怎么办?

如果我想将数组大小作为参数传递给函数怎么办?

据我了解,如果在调用函数时知道大小,则在调用函数时在堆栈上获取任意大小的数组应该没有问题。

我应该为此烦恼吗?据我了解,将这个固定大小的数组放在堆栈上会提高性能,因为没有完成堆分配。

【问题讨论】:

Should I be bothered by this? 可能不会。听起来你过早地优化和思考太低了。 stackalloc 可用于强制分配一定数量的字节的堆栈。它有它的用途,但你应该非常确定你需要它 - 大多数程序(尤其是业务线应用程序)不需要它。 堆栈分配的数组在所有恶意软件攻击中占很大比例。 【参考方案1】:

10 个 int 结构将分配在堆上,只有指向它们的指针会在堆栈上,对吗?

是的,正确。

如何将固定大小的数组放入堆栈?如果我使用我定义的结构怎么办?

stackalloc keyword 用于此目的。但是,这仅适用于不安全的上下文,这在大多数情况下是一个相当不必要的限制因素,不值得在性能上进行权衡。

例子:

public void unsafe foo()

    int* bar = stackalloc int [10];

您必须使用 pointer arithmetic 来访问数组的成员。

如果我想将数组大小作为参数传递给函数怎么办? 据我了解,如果在调用函数时知道大小,则在调用函数时在堆栈上获取任意大小的数组应该没有问题。

按预期工作:

public void unsafe foo(int length)

    int* bar = stackalloc int [length];

我应该为此烦恼吗?据我了解,将这个固定大小的数组放在堆栈上会提高性能,因为没有完成堆分配。

不,一般不会。除非您处理一些非常具体的性能关键场景,例如繁重的数学计算、加密、压缩等,否则它不会带来真正的好处。

另外,请参阅this question 以了解与性能相关的讨论。

【讨论】:

谢谢,我喜欢人们如何对堆栈溢出的一些琐碎问题给出真正彻底的解释。 除了stackalloc,您还可以在堆栈上分配固定大小的缓冲区。例如:unsafe struct foo public fixed int bar[10]; Span<T> 类型的添加意味着不再需要不安全的指针。 public void foo() Span<int> bar = stackalloc int [10]; 在编译时大小未知的情况下,为什么甚至可以在堆栈上分配数组? @algo:这是一个问答网站;这听起来像是一个问题的候选人。但是,在您发布问题之前,我会先考虑一下。根据定义,在程序运行之前不会进行分配。为什么 compiler 缺乏某些知识这一事实与运行时的行为相关?在你提问之前澄清你的问题。

以上是关于c# 啥时候在栈上分配数组?的主要内容,如果未能解决你的问题,请参考以下文章

Go 语言中的变量究竟是分配在栈上还是分配在堆上?

堆和栈的区别 还有啥建立在堆上 啥建立在栈上

内存分配

C语言里,啥时候用数组啥时候用指针和动态内存(malloc/calloc)?

java 内存简介

内存管理