一个遗留应用程序在启动时处于一个没完没了的循环中;我不知道为什么/怎么回事(代码混淆竞赛候选人),但是关于被一遍又一遍地调用的方法(这个方法是从其他几个方法调用的),我想,“我想知道调用它的方法之一是不是也调用了另一个方法呢?”
我想:“不,编译器应该能搞清楚,而且不允许它,或者至少发出警告!”
所以我创建了一个简单的应用程序来证明情况是这样的:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
method1();
}
private void button2_Click(object sender, EventArgs e)
{
method2();
}
private void method1()
{
MessageBox.Show("method1 called, which will now call method2");
method2();
}
private void method2()
{
MessageBox.Show("method2 called, which will now call method1");
// Note to self: Write an article entitled, "Copy-and-Paste Considered Harmful"
method1();
}
}...but不!它编译得很好。为什么编译器标记这段代码充其量不值得怀疑呢?如果任何一个按钮被捣碎,你就永远不会着陆!
好吧,有时候你可能想要一个没完没了的循环(起搏器代码等等),但我仍然认为应该发出警告。
发布于 2014-05-02 17:41:42
这不是一个无穷无尽的循环,而是一个没完没了的递归。这更糟糕,因为它们可能导致堆栈溢出。在大多数语言中,都不需要无休止的递归,除非您正在编写恶意软件。然而,无止境的循环往往是故意的。服务通常在无休止的循环中运行。
为了检测这种情况,编译器必须按照方法调用来分析代码;但是,C#编译器将此过程限制在当前方法中的直接代码上。在这里,可以跟踪未初始化或未使用的变量,例如可以检测到不可访问的代码。在编译速度和静态分析和优化的深度之间需要进行权衡。
而且,很难知道程序员的真正意图。
假设您编写了一种完全合法的方法。突然,因为您从另一个地方调用此方法,编译器会抱怨并告诉您,您的方法不再合法。我已经看到了大量这样的帖子:“我的方法昨天编译了。今天它不再编译了。但是我没有改变它”。
发布于 2014-05-02 17:32:02
发布于 2014-05-02 17:33:04
简单地说:,质疑您的编码模式不是编译器的工作。
您很可能编写一个Main方法,它只会抛出一个Exception。这是一种更容易检测的模式,也是一件更愚蠢的事情;然而,编译器将很高兴地允许您的程序编译、运行、崩溃和刻录。
尽管如此,从技术上讲,对于编译器来说,无休止的循环/递归是完全合法的,因此没有理由抱怨它。
实际上,很难在编译时发现循环在运行时是无法中断的。可能会引发异常,用户交互可能发生,状态可能在特定线程上的某个位置发生更改,在您正在监视的端口上发生更改,等等。任何代码分析工具都有太多的可能性来确定,毫无疑问,一个特定的递归代码段将不可避免地在运行时造成溢出。
我认为防止这种情况的正确方法是通过单元测试组织。您在测试中包含的代码路径越多,您就越不可能面对这样的情况。
https://stackoverflow.com/questions/23433648
复制相似问题