12

我有一个程序,我需要打破一大堆嵌套的 for 循环。到目前为止,大多数人一直告诉我这样做的方式是在我的代码中使用丑陋的 goto。

现在,如果我在我的循环中创建了一堆本地堆栈(我认为这就是它们的名称,如果不是,我的意思是不使用新命令的常规变量)变量,并且我的程序会触发触发 goto 的那个 if 语句,由于我的程序不正确地退出许多循环并且没有清理局部变量,我会遇到内存泄漏吗?

4

10 回答 10

20

不,您不会导致内存泄漏。使用 agoto不是“不正确地退出循环”。从代码结构的角度来看,通常不建议这样做。

除此之外,当您离开循环时,局部变量将超出范围并在此过程中从堆栈中弹出(即清理)。

于 2009-08-11T02:28:45.577 回答
6

堆栈变量(autos,而不是 autobots)不像通过 new() 或 malloc() 分配的变量那样“泄漏”。

至于 goto 的“丑陋”,那只是教条。阅读 Knuth,他和 Dijkstra 一样出色。http://pplab.snu.ac.kr/courses/adv_pl05/papers/p261-knuth.pdf避免基于意大利面的编程,但小心使用不会退化为意大利面。

Dijkstra 不喜欢它们,因为您可以使用 goto 执行的大部分操作都可以使用其他结构化编程技术完成,并且使用更少的代码,因此使其他结构化编程更不容易出错。

了解 goto 不应该是您的第一个解决方案,并且不要竭尽全力使用它们,但如果有意义,请不要屈服于教条的 lench 暴民。break 语句只是变相的 goto,专为严格遵守“您不应使用 goto”诫命没有意义的情况而设计。

于 2009-08-11T02:52:38.237 回答
2

不可以。您只能泄漏动态分配的内存。

于 2009-08-11T02:27:31.773 回答
2

堆栈变量在您进入函数时被定义(并分配),并在您离开函数时被隐式消除(因为整个调用堆栈记录被弹出)。函数内部的任何弹跳都不可能对一直分配的内存造成任何破坏。无论您通过代码采用何种执行路径,当控制权返回到调用函数时,堆栈记录都会弹出,并且内存将被释放。

于 2009-08-11T02:27:53.020 回答
1

Goto 并不总是很糟糕,但在您的情况下,您可能不应该使用 goto。

在此处此处查看很好地使用 goto 的示例。

如果您转到超出范围的标签,则堆栈上的对象将被释放。

例子:

#include <iostream>
using namespace std;

class A
{
public:
  ~A() 
  {
     cout<<"A destructor"<<endl;
  }
};



int main(int argc, char**argv)
{
  {
    A a;
    cout<<"Inside scope"<<endl;
    goto l;
    cout<<"After l goto"<<endl;
  }

  cout<<"Outside of scope before l label"<<endl;

l:
  cout<<"After l label"<<endl;
  return 0;
}

这将打印:

作用域内
的析构函数
在 l 标签之后

于 2009-08-11T02:28:16.467 回答
1

其他答案是正确的....但是,如果您必须以不同的方式嵌套循环,我会质疑将它们放在那里的设计。将该逻辑拆分为单独的函数将是解决此类问题的更好方法。

比利3

于 2009-08-11T02:30:21.347 回答
0

不,你不会的。

但是,请确保正确释放任何外部资源。例如,如果您打开一个文件,则可以跳过通常关闭的位置。

于 2009-08-11T02:27:19.573 回答
0

没有。局部变量不需要单独清理。当堆栈弹出时,所有局部变量都会随之消失。

于 2009-08-11T02:27:28.700 回答
0

不,如果您使用 goto 语句跳出循环,则循环中的任何自动变量都不会导致编程泄漏。

于 2009-08-11T02:29:41.020 回答
0

向后 goto 会泄漏资源吗?或以下代码的任何其他潜在问题?

重新执行:

        try
        {
            //Setup request
            HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);

            ....

            //Get Response
            HttpWebResponse response = (HttpWebResponse)request.GetResponse();

           if(response != HttpStatus.OK && noOfRetries < 3)
            {
                noOfRetries++;
                Thread.Sleep(10 * 1000);


                response.Close();
                goto Reexecute;
            }
            ...

            response.Close();
         }
         catch
         {

         }
于 2010-12-03T07:01:07.447 回答