一尘不染

C#未初始化的变量有危险吗?

c#

我熟悉C#规范的5.3节,其中说必须在使用前分配一个变量。

在C和非托管C ++中,这是有道理的,因为不会清除堆栈,并且用于指针的内存位置可能在任何地方(导致难以跟踪错误)。

但是我给人的印象是运行时并没有真正“未分配”的值。特别是,未初始化的引用类型将始终具有null值,永远不会具有先前调用方法或随机值后遗留下的值。

这是正确的吗?还是我错误地认为这些年来检查空值就足够了?您可以在C#中使用真正的非初始化变量吗,还是CLR会处理这个问题,并且总是设置了一些值。


阅读 326

收藏
2020-05-19

共1个答案

一尘不染

我的印象是,运行时没有真正“未分配”的值。特别是,未初始化的引用类型将始终具有null值,永远不会具有先前调用方法或随机值后遗留下的值。
它是否正确?

我注意到,实际上还没有人回答您的问题。

您实际提出的问题的答案是“ sorta”。

正如其他人指出的那样,某些变量(数组元素,字段等)被归类为自动“初始分配”为其默认值。(对于引用类型,其为null;对于数字类型,其为零;对于布尔类型,其为false;对于用户定义的结构,其自然递归)。

某些变量未归类为初始分配。特别是局部变量最初并未分配。在使用它们的 值的 所有点上,编译器都必须将它们分类为“绝对分配” 。

然后,您的问题实际上是“归为 未明确分配 的局部变量是否实际上 最初 以与字段相同的方式 分配 ?” 这个问题的答案是 肯定的
,实际上,运行时最初会分配所有本地人。

这有几个不错的属性。首先,您可以在调试器中观察它们在第一次分配之前处于默认状态。第二,垃圾回收器不会被欺骗去引用错误的指针,只是因为堆栈上有垃圾被当作托管引用了。等等。

如果可以安全地运行时,则 允许
运行时将本地人的初始状态保留为偶然发生的任何垃圾。但是,作为实现细节,它永远不会选择这样做。它积极地将局部变量的内存清零。

那么,使用本地语言之前必须明确分配本地语言的规则的原因 并不是
防止您观察本地垃圾的未初始化状态。这已经是不可观察的了,因为CLR会积极地将局部变量清除为其默认值,就像对字段和数组元素一样。
在C#中这是非法的,是因为使用未分配的本地很可能会成为错误。 我们只是将其设为非法,然后编译器阻止您出现此类错误。

2020-05-19