2010-05-14 44 views
3

好吧,也许这并不是很了不起,因为我不太了解调试器是如何工作的,更不用说编辑和继续了,这完全是令人惊叹的。Visual Studio Debugger Voodoo

但我不知道是否有人知道什么是调试器与在此方案中的变量声明做。我可以通过我的代码进行调试,提前执行一行 - 通过变量初始声明和赋值,代码仍然可以正常运行。如果它是一个值类型,它将具有默认值,对于ref类型为null。

所以,如果我创建一个使用可变它宣布它不会编译前的功能,但如果我使用调试器来运行它,这样,它仍然会运行没有错误。为什么是这样?这是否与你不能在声明中放置断点有关?

回答

4

是的,这些声明更具结构性。它们是在调用方法时分配的堆栈中的当地人的一部分。你不能打破他们,因为他们并不真正发生在你写的地方 - 他们不是说明。

究其原因,编译器不会让你使用他们,他们声明主要是为自己的清醒之前 - 你总是知道找了一个声明。方法内变量的复杂范围将进一步说明这一点。

1

根据文章Gain performance by not initializing variables

在.NET中,公共语言运行库(CLR)中明确,尽快为他们创建初始化所有变量。值类型初始化为0,引用类型初始化为null。

想必调试已经知道这些变量要么是因为代码已经被编译或(现在看来不太可能,我打字,但)调试器是足够聪明来检测一个变量被宣布。

+0

这就是我想知道的。它看起来好像A)编译器只是防守,并试图在我应该之前保护我不使用变量,或者B)调试器实际上正在做一些不同的事情。你说得对,只要我输入,我认为'该死的,我真的不希望';) – LoveMeSomeCode 2010-05-14 20:10:33

1

我认为,因为你使用调试器,你是混淆了两个不同的活动,编译和执行,以及两种不同类型的声明,声明和功能。

当您编译时,声明性语句会告诉编译器为您的变量保留一些内存。它说:“哦,你想声明一个名为”wombatCount“的整数;好吧,我将取地址0x1234并为你保留四个字节,并在它们上面贴上一个名为wombatCount的标签。”在编译期间会发生这种情况,在运行代码之前很久。 *

当你在调试器中执行代码,您运行的代码,因此它已经知道每次的内存就为您预留字节。变量wombatCount已经与地址为0x1234的四个字节相关联,因此它可以随时访问和更改该数据,而不仅仅是在声明语句之后。当然,你的程序不能,但调试器可以。

,你在代码中使用它之前宣布的存储器中的C#语言的语法要求,但是这只是语言定义的一部分,而不是所有的编译器的硬和快速的要求。有些语言根本不需要预先声明变量,甚至还有一些古代语言,您可以在代码中的任意位置声明变量,而不仅仅是在“上面”使用它们。但是语言开发人员现在明白,语言语法对于人类理解来说是最重要的,并且不再是为了便于机器编码或帮助编译器编写人员,所以通常创建现代语言语法以尽可能地帮助程序员。这意味着减少混淆,所以“声明必须首先”是一种常见的规则,可以帮助您避免错误。(*为了在技术上更加正确,我相信在.Net中,标签只在编译时与指针列表相关联,这些指针列表将在运行时保留内存,但数据字节直到您使用才会实际分配它们的区别在于内在的,对你的理解来说并不重要,重要的是在编译期间声明式声明预先声明了标签。)

+0

因此,在运行时,4个字节实际指定的时间是什么时候?当程序第一次启动时?或者当变量进入范围时,即在声明它的方法开始时? – LoveMeSomeCode 2010-05-18 12:34:42

+0

如果是局部变量或方法参数,则在调用方法时分配它。如果变量是一个引用类型(不是简单的像一个int或一个布尔,而不是一个结构),那么当对象是new()'d时,内存被分配在堆上 – 2010-05-18 14:58:39

相关问题