在 Linux 内核代码中使用 goto 毫无意义
Use of goto in Linux kernel code makes no sense
我正在查看 Linux 源代码,here 我无意中发现了这个函数:
static int check_free_space(struct bsd_acct_struct *acct)
{
struct kstatfs sbuf;
if (time_is_after_jiffies(acct->needcheck))
goto out;
/* May block */
if (vfs_statfs(&acct->file->f_path, &sbuf))
goto out;
if (acct->active) {
u64 suspend = sbuf.f_blocks * SUSPEND;
do_div(suspend, 100);
if (sbuf.f_bavail <= suspend) {
acct->active = 0;
pr_info("Process accounting paused\n");
}
} else {
u64 resume = sbuf.f_blocks * RESUME;
do_div(resume, 100);
if (sbuf.f_bavail >= resume) {
acct->active = 1;
pr_info("Process accounting resumed\n");
}
}
acct->needcheck = jiffies + ACCT_TIMEOUT*HZ;
out:
return acct->active;
}
我觉得 Marco 使用 goto
没有多大意义,尤其是因为它导致 return
语句。为什么函数没有这样重写:
static int check_free_space(struct bsd_acct_struct * acct) {
struct kstatfs sbuf;
if (time_is_after_jiffies(acct->needcheck) ||
vfs_statfs( &acct->file->f_path, & sbuf)) {
//latter may block
return acct->active;
}
if (acct->active) {
u64 suspend = sbuf.f_blocks * SUSPEND;
do_div(suspend, 100);
if (sbuf.f_bavail <= suspend) {
acct->active = 0;
pr_info("Process accounting paused\n");
}
} else {
u64 resume = sbuf.f_blocks * RESUME;
do_div(resume, 100);
if (sbuf.f_bavail >= resume) {
acct->active = 1;
pr_info("Process accounting resumed\n");
}
}
acct->needcheck = jiffies + ACCT_TIMEOUT * HZ;
}
我听说 goto
如果用于跳出嵌套循环或用于内存清理,它确实很有用。这两种情况都不是这里的情况,那么为什么 Marco 选择 goto
s 呢?一定有某种正当理由,对吧?
Why wasn't the function re-written like this
您刚刚编写的函数无效。更准确地说,如果没有输入此块:
if (time_is_after_jiffies(acct->needcheck) ||
vfs_statfs( &acct->file->f_path, & sbuf)) {
vfs_statfs( &acct->file->f_path, & sbuf)) {
//latter may block
return acct->active;
}
那么该函数将无法在其他任何地方执行有效的 return
。代码甚至无法编译。
该特定函数中 goto
的目的是执行 早期 return 而无需复制 return acct->active;
行.这是一种非常常见的模式,它可以节省重复的代码行,有时还可以减小生成的可执行文件的大小。
就是"single return"的原则。一些程序员认为任何时候都应该遵守。
如果将 goto out;
替换为 return acct->active;
,该函数将完全相同
这是一个关于单身的问题return:Should a function have only one return statement?
我正在查看 Linux 源代码,here 我无意中发现了这个函数:
static int check_free_space(struct bsd_acct_struct *acct)
{
struct kstatfs sbuf;
if (time_is_after_jiffies(acct->needcheck))
goto out;
/* May block */
if (vfs_statfs(&acct->file->f_path, &sbuf))
goto out;
if (acct->active) {
u64 suspend = sbuf.f_blocks * SUSPEND;
do_div(suspend, 100);
if (sbuf.f_bavail <= suspend) {
acct->active = 0;
pr_info("Process accounting paused\n");
}
} else {
u64 resume = sbuf.f_blocks * RESUME;
do_div(resume, 100);
if (sbuf.f_bavail >= resume) {
acct->active = 1;
pr_info("Process accounting resumed\n");
}
}
acct->needcheck = jiffies + ACCT_TIMEOUT*HZ;
out:
return acct->active;
}
我觉得 Marco 使用 goto
没有多大意义,尤其是因为它导致 return
语句。为什么函数没有这样重写:
static int check_free_space(struct bsd_acct_struct * acct) {
struct kstatfs sbuf;
if (time_is_after_jiffies(acct->needcheck) ||
vfs_statfs( &acct->file->f_path, & sbuf)) {
//latter may block
return acct->active;
}
if (acct->active) {
u64 suspend = sbuf.f_blocks * SUSPEND;
do_div(suspend, 100);
if (sbuf.f_bavail <= suspend) {
acct->active = 0;
pr_info("Process accounting paused\n");
}
} else {
u64 resume = sbuf.f_blocks * RESUME;
do_div(resume, 100);
if (sbuf.f_bavail >= resume) {
acct->active = 1;
pr_info("Process accounting resumed\n");
}
}
acct->needcheck = jiffies + ACCT_TIMEOUT * HZ;
}
我听说 goto
如果用于跳出嵌套循环或用于内存清理,它确实很有用。这两种情况都不是这里的情况,那么为什么 Marco 选择 goto
s 呢?一定有某种正当理由,对吧?
Why wasn't the function re-written like this
您刚刚编写的函数无效。更准确地说,如果没有输入此块:
if (time_is_after_jiffies(acct->needcheck) ||
vfs_statfs( &acct->file->f_path, & sbuf)) {
vfs_statfs( &acct->file->f_path, & sbuf)) {
//latter may block
return acct->active;
}
那么该函数将无法在其他任何地方执行有效的 return
。代码甚至无法编译。
该特定函数中 goto
的目的是执行 早期 return 而无需复制 return acct->active;
行.这是一种非常常见的模式,它可以节省重复的代码行,有时还可以减小生成的可执行文件的大小。
就是"single return"的原则。一些程序员认为任何时候都应该遵守。
如果将 goto out;
替换为 return acct->active;
这是一个关于单身的问题return:Should a function have only one return statement?