Зачем goto в исходниках Python?

Нашел такой код в исходниках питона. Можете объяснить зачем goto в данном контексте? На сколько мне известно использование goto в принципе считается плохим кодом. А тут он еще и странно применен.
static int
win32_urandom_init(int raise)
{
    /* Acquire context */
    if (!CryptAcquireContext(&hCryptProv, NULL, NULL,
                             PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
        goto error;

    return 0;

error:
    if (raise)
        PyErr_SetFromWindowsErr(0);
    else
        Py_FatalError("Failed to initialize Windows random API (CryptoGen)");
    return -1;
}
  • Вопрос задан
  • 1082 просмотра
Решения вопроса 2
un1t
@un1t
Стандартная практика обработки ошибок или освобождения ресурсов в Си. Обычно в таких случаях goto более удобен и читаем чем альтернативные решения.
Однако в данном конкретном примере функция очень короткая и в ней нет множества ветвлений, поэтому конечно проще написать без goto, но видимо сила привычки или задел на будущее.

Вот напиример функция из питона с более уместным использованием goto

static int
ast_type_init(PyObject *self, PyObject *args, PyObject *kw)
{
    Py_ssize_t i, numfields = 0;
    int res = -1;
    PyObject *key, *value, *fields;
    fields = _PyObject_GetAttrId((PyObject*)Py_TYPE(self), &PyId__fields);
    if (!fields)
        PyErr_Clear();
    if (fields) {
        numfields = PySequence_Size(fields);
        if (numfields == -1)
            goto cleanup;
    }

    res = 0; /* if no error occurs, this stays 0 to the end */
    if (numfields < PyTuple_GET_SIZE(args)) {
        PyErr_Format(PyExc_TypeError, "%.400s constructor takes at most "
                     "%zd positional argument%s",
                     Py_TYPE(self)->tp_name,
                     numfields, numfields == 1 ? "" : "s");
        res = -1;
        goto cleanup;
    }
    for (i = 0; i < PyTuple_GET_SIZE(args); i++) {
        /* cannot be reached when fields is NULL */
        PyObject *name = PySequence_GetItem(fields, i);
        if (!name) {
            res = -1;
            goto cleanup;
        }
        res = PyObject_SetAttr(self, name, PyTuple_GET_ITEM(args, i));
        Py_DECREF(name);
        if (res < 0)
            goto cleanup;
    }
    if (kw) {
        i = 0;  /* needed by PyDict_Next */
        while (PyDict_Next(kw, &i, &key, &value)) {
            res = PyObject_SetAttr(self, key, value);
            if (res < 0)
                goto cleanup;
        }
    }
  cleanup:
    Py_XDECREF(fields);
    return res;
}
Ответ написан
Комментировать
leahch
@leahch
3D специалист. Dолго, Dорого, Dерьмово.
Как ни странно, я тоже в свое время считал, что goto плохо и дурной вкус. Нет, не плохо! Иногда читаемость, как в данном примере, повышается на порядок. И goto плохо там, где его неправильно применяют.
Более того, внутри любой цикл все равно раскладывается на jmp и br :-)
Так что все зависит от квалификации и применения.
Goto перестали рекомендовать, из-за того, что очень просто с ним пропустить освобождение чего-то важного. Так что новичкам его лучше не пользовать, это очень точный инструмент.
From: Linus Torvalds
Subject: Re: any chance of 2.6.0-test*?
Date: 	Sun, 12 Jan 2003 11:38:35 -0800 (PST)

On Sun, 12 Jan 2003, Rob Wilkens wrote:
> 
> I'm REALLY opposed to the use of the word "goto" in any code where it's
> not needed.

I think goto's are fine, and they are often more readable than large
amounts of indentation. That's _especially_ true if the code flow isn't
actually naturally indented (in this case it is, so I don't think using
goto is in any way _clearer_ than not, but in general goto's can be quite
good for readability).

Of course, in stupid languages like Pascal, where labels cannot be 
descriptive, goto's can be bad. But that's not the fault of the goto, 
that's the braindamage of the language designer.

		Linus
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@res2001
Developer, ex-admin
Вызывается обработчик ошибок.

В исходниках питона такое сплошь и рядом, они используют подобных подход для обработки ошибок (и еще в некоторых других вариантах) - в Си нет исключений.
Просто вам попалась короткая функция, поэтому это режет глаз.
В достаточно развесистой функции это кажется нормальным. Хотя можно было бы применить структурный подход, вместо goto.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы