我有一个关于方法调用和堆栈指针的问题。
基本上我有一个程序可以读取用户的输入。创建类的对象"输入"后,方法调用" prompt()"提供一个包含选项的菜单,您所做的每个选择都会调用一个执行某些操作的新方法。做出选择后,您始终可以选择返回主菜单,此操作会调用" prompt()"再次。
现在,我的问题是,每次调用"提示()"指向内存堆栈中的新位置还是会进入与第一次调用时相同的上下文?即,可以一遍又一遍地回到主菜单来创建内存泄漏吗?
class inOut {
public string[] Prompt(){
...
presentChoices();
...
}
private void PresentChoices(){
...
if(someChoice){
manualInput();
}
...
}
private void ManualInput(){
...
if(goBack){
Prompt();
}
...
}
}
我希望问题很明确,并提前感谢任何答案!
答案 0 :(得分:0)
对于您输入的每种方法,都应该有相应的return
。否则可能会导致StackOverlow
。它不是新的上下文,而是堆栈中剩余的值,用于return
返回到调用方法的位置以及方法调用本身(通过参数)。
要拥有重复某些内容,您可以使用无限循环:
while(true)
{
... // repeat this action
if(endcondition)
break;
}
在您的情况下,重复操作是调用prompt()
来显示菜单。它可能具有返回值,无论何时重复或退出,都可以在endcondition
中使用。
答案 1 :(得分:0)
只要在同一个对象实例上调用该方法,它就会成为指向同一个地址的指针。
当您创建对象的新实例时,每个对象都有自己的指针。 如果要避免这种情况,则需要将方法定义为静态。在这种情况下,您将不是从实例而是从类型调用该方法。
特别是当您从同一实例上下文中反复调用相同的方法时,需要注意的是递归调用。对于许多递归调用(数千个)将导致StackOverFlowException(如此网站的名称)。您可以在Visual Studio的StackTrace窗格中查看是否有递归调用,或者如果安装了Resharper,它将在文档的左侧告诉您。
无论哪种方式,你在这里描述的并不是真正的“内存泄漏”(ML是未使用的对象,不会被收集并留在内存中没有做任何事情)而是堆栈溢出情况。
答案 2 :(得分:0)
不再引用的对象是垃圾回收。记录Input对象会发生什么。
... Unlesss
......你做错了。
在Winform应用程序中,如果由于某种原因涉及事件处理程序(事件的发布者比订阅者的寿命更长)阻止垃圾回收,通常会发生错误。
答案 3 :(得分:0)
假设您的代码如下所示:
void Prompt()
{
// ...
var obj = new Input();
// ...
if (someCondition)
{
Prompt(); // recursive
}
// ...
// Is 'obj' used here?
}
然后当你递归地调用Prompt()
时,是的,创建了一个新的上下文。 obj
变量将指向新对象等。
如果递归变得非常非常深,你可能得到一个StackOverflowException
(堆栈中没有更多的空间用于新的“调用帧”),或者你可能得到OutOfMemoryException
(不再有堆) Input
个实例的空间。
但是,如果您因某种原因知道递归不会变得太深,那么垃圾收集器会在安全的情况下为您清理。
但也许您应该考虑使用while
(或do
)循环,而不是让您的方法自行调用?这实际上取决于你想要达到的目标。
我可能误解了你的问题。可能Prompt()
本身不会调用Prompt
?你应该给出简化的代码结构(比如我上面的代码示例),以便明确从哪里调用什么。