仅使用 GOTO 语句跳下来有什么害处吗?还是我们完全安全?
我的意思是认为这是我的代码,
Some code ...
...
GOTO whereToJump
Some code ...
...
whereToJump:
Some code ...
当 whereToJump 点始终低于 GOTO 语句时,是否存在安全问题?
这是最著名的计算机科学论文之一的主题。转到Dijkstra 认为有害的声明。它基本上表明没有人需要 goto(我知道一如既往有一些例外)。
这是 1968 年,但今天仍然非常可读。
当需要从许多位置向下跳转到代码块时,我使用 goto 语句。通常没有 goto 语句,这可能需要编写另一个函数(这样上面的代码块不会在第一个函数中重复)并在第一个函数中调用。goto 的效率不低于 if 或 switch 语句,因为它还利用 if、switch 等使用的 jumb 语句之一(jz、jnz 等)。
有意义的是,只有向下跳跃才能减少意大利面条式代码的潜力。(根据我的经验,在调试基于 GOTO 的遗留代码时,75% 的头痛来自向上 goto 导致混乱循环的情况)
但是,鉴于您只使用向下跳跃,应该很容易转换为非基于 goto 的代码。我不确定您的 goto 会提供多少改进。
在任何更复杂的示例中,如果您可以决定仅使用 GOTO在同一范围内跳转,则可以使用 if 语句。(如果不在同一个范围内,那也不是真的“只是向前跳”吧?)
(当然,如果你的真实代码没有比这更复杂,你可以去掉第二块“一些代码......”)
有了这个评论,我不鼓励使用 GOTO,而只是为了说明在某些非常具体的情况下它可能很有用。到目前为止,在实践中我还没有看到任何使用goto
语句向上或向下跳转的代码,但是有一个特定的用例我发现goto
它更具可读性。goto
这是我认为更有意义的代码示例。
void fun_test ()
{
.code..
allocate dynamic memory.
acquire_lock();
//do some action, call api.
if (some error) {
print error;
free memory;
unlock();
return FAIL;
} else {
// some code.
}
if (some_other error) {
print error;
free memory;
unlock();
return FAIL;
}
:
:
// more error condition checks.
:
return SUCCESS
}
void fun_test_withgoto ()
{
error_code rc = SUCCESS;
.code..
allocate dynamic memory.
acquire_lock();
//do some action, call api.
if (some error) {
rc = <Failure id>;
goto function_cleanup;
} else {
// some code.
}
if (some_other error) {
rc = <failure id>;
goto function_cleanup;
}
:
:
// more error conditions.
:
function_cleanup:
if (rc == SUCCESS) {
print "Success..";
} else {
print "Error : <failure id>";
}
free_memory();
unlock();
return(rc);
}
goto不会使代码的安全性降低,与您跳转的方式无关。
您可以按照自己喜欢的方式构建代码。是您的代码决定代码的好坏。goto 在某些情况下可能是合适的(不,我可以举一个例子:-))
goto 的问题在于它可能会隐藏程序中的执行流程,使代码混乱。但是,如果您创建易于阅读/维护的代码,那么这不是问题。
嗯,真的没有问题。该代码相当于:
Some code ...
...
if (false)
{
Some code ...
...
}
Some code ...
也就是说,我不会这样做。好的用例goto
非常少见,而其他流控制结构在 C# 中更为惯用。
这些天应该避免 GOTO 的主要原因是程序员一般不再习惯 GOTO(这是一件好事)。因此,如果您编写大量使用 GOTO 的代码,那么您的程序员同伴很可能难以理解和扩展它。
更糟糕的是,随着同事开始使用越来越多的 GOTO,到处出现 GOTO 可能会导致破窗综合症,直到你只剩下一大碗意大利面。
xkcd 说得最好...