Будет ли «Гарантированное исключение копирования» (P0135, C++1z) потенциально требовать взлома ABI?

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html

Вышеупомянутое предложение для «Гарантированного устранения копирования» было включено в рабочий документ C++ на собрании в июне 2016 года в Оулу, Финляндия, за которое затем проголосовали за публикацию в качестве проекта комитета. Надеюсь, это приведет к публикации стандарта C++17 в следующем году.

В предложении разъясняются различные категории значений, включающие временные объекты, чтобы обеспечить отсутствие вызовов конструктора копирования в определенных случаях использования.

Мой вопрос: "Может ли это новое требование нарушить совместимость с ABI для компиляторов, которые ранее не выполняли исключение копирования в этих обстоятельствах или реализовали его таким образом, который не будет совместим с новыми требованиями?"

Я имею в виду такие вещи, как инициализация, которая исключает копии, когда создание объекта может быть встроено, но не при пересечении границ единиц компиляции.


person Phil Miller    schedule 26.06.2016    source источник
comment
Я могу представить себе ABI (хотя и нелепый), который будет нарушен этим изменением. Будет ли этого достаточно, или вы ищете настоящие экземпляры ABI, которые на самом деле используются настоящим неигрушечным компилятором, который ломается?   -  person Yakk - Adam Nevraumont    schedule 26.06.2016
comment
Как можно сломать то, чего нет?   -  person user3104201    schedule 26.06.2016
comment
Я думаю о таких вещах, как инициализация, которая пропускает копии, когда создание объекта может быть встроено, но не при пересечении границ единицы компиляции. Я не знаю таких обстоятельств, при которых это было бы возможно.   -  person Nicol Bolas    schedule 26.06.2016
comment
предложение отличное. Всегда было бы хорошо иметь авто   -  person Curious    schedule 26.06.2016
comment
Я думал, что у меня есть пример того, что сейчас делают компиляторы, что не разрешено новыми правилами, но я на самом деле подозреваю, что это не разрешено и по текущим правилам, поскольку ему удается избежать копирования и, таким образом, полностью скопировать elision. Я задал это как новый вопрос, но вы, возможно, захотите подумать, могут ли небольшие изменения, чтобы ввести исключение копирования, могут дать вам ответ: stackoverflow.com/questions/38043288 /   -  person    schedule 27.06.2016
comment
@Yakk Я искал один или несколько реальных экземпляров ABI, используемых каким-то неигрушечным компилятором, который ломается.   -  person Phil Miller    schedule 27.06.2016
comment
Интересные новости со встречи в Оулу (это, кстати, соседний город через границу от Лулео). Я долгое время утверждал, что не что иное, как гарантия от стандарта, достаточно хороша, чтобы иметь возможность использовать возвраты копии в критически важном для производительности / жестком коде реального времени. Однако обратите внимание на фразу «Эта статья касается только первого случая. Хотя мы считаем, что надежный NRVO (оптимизация возвращаемого значения, вторая пуля) является важной функцией, позволяющей рассуждать о производительности, случаи, когда NRVO возможен, малозаметны, и дать простую гарантию сложно».   -  person Erik Alapää    schedule 27.06.2016


Ответы (1)


Когда функция вызывается, функция должна вернуть значение. Это значение нуждается в памяти, чтобы жить, но возвращаемое значение должно пережить саму функцию. ABI определяет, как все это работает. Вообще говоря, это происходит из-за того, что вызывающая сторона предоставляет часть памяти размера/выравнивания для возвращаемого значения функции.

Таким образом, если функция вычисляет значение и возвращает его, она должна (теоретически) скопировать это вычисленное значение в память возвращаемых значений. И когда вызывающий объект извлекает его, он должен (теоретически) скопировать эту память возвращаемого значения в какой-либо другой объект стека для последующего использования.

Негарантированное удаление копии говорит о том, что ни одна из этих копий не нужна. Что касается возвращающей функции, то компилятору разрешено просто использовать внутреннюю память возвращаемого значения при генерации этого значения, поэтому оператору return не нужно ничего копировать. А на принимающей стороне, если память будет использоваться для инициализации объекта стека, ему не нужно копировать в эту память.

Гарантированное удаление копии говорит о том, что если принимающая сторона инициализирует объект того же типа, то получатель не будет учитывать, есть ли у объекта конструктор копирования/перемещения. Таким образом, код, вызывающий такую ​​функцию, как auto t = Func();, не будет рассматривать ее как потенциальную операцию копирования в t. Компилятор, обрабатывающий этот код, вызовет Func с памятью возвращаемых значений, которая находится в пространстве стека для t.

А на стороне вызываемого объекта, если вы возвращаете prvalue напрямую, то нет необходимости в существовании конструктора копирования/перемещения. Вызываемый объект создаст значение prvalue непосредственно в памяти возвращаемого значения.

Вот в чем дело: ABI не заботятся ни о чем из этого. Все, о чем заботится ABI, — это низкоуровневая память. То есть до тех пор, пока вызывающий объект передает память возвращаемого значения соответствующего размера и выравнивания, а вызываемый объект инициализирует эту память объектом соответствующего типа... ABI все равно .

Если вызывающая сторона хочет использовать эту память возвращаемых значений для последующих операций, это нормально для ABI. Если вызываемый объект хочет инициализировать данные непосредственно в памяти возвращаемых значений, а не копировать их, ABI этого не заметит.

ABI определяет интерфейс; что вы делаете с этим интерфейсом, зависит от вас.

В качестве примера рассмотрим ITanium ABI для возвращаемых значений. Это позволяет хранить типы классов в регистрах, но только, если у них есть тривиальные конструкторы копирования/перемещения. В противном случае, независимо от их содержимого, они должны быть построены в памяти, предоставленной вызывающей функцией. Если класс тривиально копируется, то вы не можете сказать разницу между элизией и не-элизионностью.

Единственный способ, которым ABI может создать проблему для этой функции, — это если ABI произвольно решает, где хранить возвращаемое значение (и, предположительно, параметры) относительно друг друга. То есть ABI заставляет вызывающую сторону поместить объект в стек в определенное место относительно параметров.

Может ли существовать такой ABI? У меня нет особых знаний, чтобы сказать, что это невозможно. Имеет ли это? Я довольно сомневаюсь в этом, поскольку такой ABI в целом затруднил бы элизию.

person Nicol Bolas    schedule 26.06.2016
comment
Тогда вопрос сводится к тому, существуют ли какие-либо существующие компиляторы, которые реализуют память возвращаемых значений каким-то глупым способом, из-за которого либо вызываемый объект записывает результат непосредственно в него, либо вызывающий использует результат непосредственно из него. - person Phil Miller; 27.06.2016
comment
@Novelocrat: ABI определяет, как значения механически передаются через вызовы функций. Единственный способ, которым это могло быть испорчено, - это если компилятор не следовал ABI. Что является гораздо более серьезной проблемой, чем неспособность правильно реализовать гарантированное исключение. - person Nicol Bolas; 27.06.2016
comment
@Nicol: Что, если вместо того, чтобы позволять вызывающей стороне указывать произвольное место, где будет помещено возвращаемое значение, ABI указывает его относительно чего-то еще (местоположения параметров, обратный адрес и т. д.). Тогда вызывающая сторона может быть не в состоянии избежать последующей передачи из местоположения, определенного ABI (которое может быть перезаписано дополнительными вызовами функций до истечения времени жизни объекта) в место с более длительным сроком службы. - person Ben Voigt; 27.06.2016
comment
@BenVoigt: я не эксперт по ABI; Я просто имею общее представление о том, как это работает. Так что я как бы полагаюсь на мнение комитета по стандартам. Если ни у кого не было с этим проблем, то, вероятно, нет ABI, которые делают что-то подобное. - person Nicol Bolas; 27.06.2016
comment
Пример Бена точно иллюстрирует то, что, как я думал, может происходить. - person Phil Miller; 27.06.2016