Есть ли польза от использования Py_DECREF вместо Py_XDECREF для расширений Python C?

Я работаю над документацией расширения Python C для определения новых типов и только что закончил Предоставление более точного управления атрибутами данных.

В этом разделе они изменяют код примера, чтобы гарантировать, что атрибуты first и last структуры Noddy никогда не могут быть NULL, например, инициализируя атрибуты пустыми строками в new и добавляя геттеры и сеттеры, которые вызывают TypeError, если пользователь пытается удалить или иным образом установить для этих атрибутов значение Null.

Кроме того (и суть моего вопроса), автор меняет все Py_XDECREF на Py_DECREF для этих атрибутов, заявляя, что:

Благодаря этим изменениям мы можем гарантировать, что первый и последний элементы никогда не будут равны NULL, поэтому мы можем удалить проверки на значения NULL почти во всех случаях. Это означает, что большинство вызовов Py_XDECREF() можно преобразовать в вызовы Py_DECREF(). Единственное место, где мы не можем изменить эти вызовы, — это делокатор, где существует вероятность того, что инициализация этих членов в конструкторе не удалась.

Мне кажется, что было бы безопаснее использовать Py_XDECREF, учитывая, что Py_DECREF приводит к segmentation fault, если передается значение NULL.

В чем преимущество использования Py_DECREF вместо Py_XDECREF?


person Matthew Moisen    schedule 28.01.2017    source источник


Ответы (1)


Если вы знаете, что объект не может быть NULL, преимущества Py_DECREF по сравнению с Py_XDECREF заключаются в следующем:

  • это быстрее, так как позволяет избежать ненужного теста и прыжка;
  • он сигнализирует (человеку) читателю, что ожидается, что указатель будет не NULL в точке освобождения;
  • он обеспечивает то, что фактически является утверждением с нулевой стоимостью, что указатель не равен NULL - программа, скорее всего, немедленно выйдет из строя, если инвариант будет нарушен.¹

Эти моменты могут быть важны при работе с низкоуровневым кодом, поэтому ядро ​​​​Python и большинство расширений стараются использовать только Py_XDECREF (или Py_CLEAR в tp_clear), когда указатель действительно может быть NULL.

¹ Технически это неопределенное поведение, что означает, что сбой не гарантирован, как это было бы с реальным утверждением. На практике, однако, у компилятора нет иного выбора, кроме как генерировать код, который разыменовывает указатель, что приведет к ошибке памяти, если он равен NULL.

person user4815162342    schedule 28.01.2017