LINUX.ORG.RU

Зачем так делать?

 ,


0

4

Копался в исходниках libcxx (реализация STL из LLVM) с целью понять как устроен basic_filebuf внутри, наткнулся на такой момент:

template <class _CharT, class _Traits>
basic_filebuf<_CharT, _Traits>*
basic_filebuf<_CharT, _Traits>::close()
{
    basic_filebuf<_CharT, _Traits>* __rt = nullptr;
    if (__file_)
    {
        __rt = this;
        unique_ptr<FILE, int(*)(FILE*)> __h(__file_, fclose);
        if (sync())
            __rt = nullptr;
        if (fclose(__h.release()))
            __rt = nullptr;
        __file_ = nullptr;
        setbuf(0, 0);
    }
    return __rt;
}

В данном случае __file__ это указатель на сишную структуру FILE, вот здесь он заворачивается в unique_ptr,

unique_ptr<FILE, int(*)(FILE*)> __h(__file_, fclose);

а вот здесь возвращают владение чтобы закрыть файл вручную и проверить что возвращает fclose:

if (fclose(__h.release()))

Правильно ли я понимаю, что это нужно лишь для того чтобы не получить висячий указатель если в sync() будет брошено исключение?

★★★★★

Последнее исправление: Meyer (всего исправлений: 1)

От исключения спасёт.

ox55ff ★★★★★
()

Видимо unique_ptr это raii, а release вызывается чтобы потом занулить __rt_. Можно было бы просто вернуть nullptr, но от этого накроется rvo. Ну хз, долго не вникал.

zerhud
()
Ответ на: комментарий от zerhud

Видимо unique_ptr это raii, а release вызывается чтобы потом занулить __rt_.

__rt это что-то типа костыля

Можно было бы просто вернуть nullptr, но от этого накроется rvo.

Не, это нужно чтобы занулить __file_ и внутренние указатели (setp/setg) даже если fclose вернет ошибку.

Meyer ★★★★★
() автор топика

Правильно ли я понимаю, что это нужно лишь для того чтобы не получить висячий указатель если в sync() будет брошено исключение?

Авторы хотели гарантировать вызов fclose() даже если sync() бросит, ни больше, ни меньше.

bugfixer ★★★★★
()
Последнее исправление: bugfixer (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.