Использование goto в Linux коде ядра не имеет смысла - PullRequest
0 голосов
/ 21 января 2020

Я просматривал исходный код Linux и здесь Я наткнулся на эту функцию:

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;
}

Я не могу найти большого смысла в использовании Марко 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 действительно может быть полезным, если его использовать для выхода из вложенного l oop или для очистки памяти , Здесь нет ни одного случая, так почему же Марко go для goto с? Должна быть какая-то веская причина, верно?

Ответы [ 2 ]

4 голосов
/ 21 января 2020

Почему функция не была переписана так:

Функция, которую вы только что написали, недействительна . Точнее, если этот блок не введен:

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 acct->active;. Это довольно распространенный шаблон, который сохраняет дублированные строки кода, а иногда и размер получаемого исполняемого файла.

0 голосов
/ 21 января 2020

Это принцип «одного возврата». Некоторые программисты считают, что его нужно всегда соблюдать * Должна ли функция иметь только один оператор возврата?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...