¿Qué significa "envenenar una función" en C++?


Al final de la charla de Scott Schurr "Introducing constexpr" en CppCon, pregunta "¿Hay alguna manera de envenenar una función"? Luego explica que esto se puede hacer (aunque de una manera no estándar) por:

  1. Poniendo un {[1] } en una función constexpr
  2. Declarando un no resuelto extern const char*
  3. Haciendo referencia a lo no resuelto extern en el throw

Siento que estoy un poco fuera de mi profundidad aquí, pero tengo curiosidad:

  • ¿Qué significa " envenenar a ¿función?
  • ¿Cuál es el significado/utilidad de la técnica que él describe?
Author: Peter Mortensen, 2015-11-27

2 answers

En general se refiere a hacer una función inutilizable, por ejemplo, si desea prohibir el uso de asignación dinámica en un programa, podría "envenenar" la función malloc para que no se pueda usar.

En el video lo está usando de una manera más específica, lo que queda claro si lees la diapositiva que se muestra cuando habla de envenenar la función, que dice "¿Una forma de forzar solo el tiempo de compilación?"

Así que está hablando de "envenenar" la función para hacerla inviable en tiempo de ejecución, por lo que es solo se puede llamar en expresiones constantes. La técnica es tener una rama en la función que nunca se toma cuando se llama en un contexto de tiempo de compilación, y hacer que esa rama contenga algo que causará un error.

Se permite una expresión throw en una función constexpr, siempre y cuando nunca se alcance durante las invocaciones de la función en tiempo de compilación (ya que no se puede lanzar una excepción en tiempo de compilación, es una operación inherentemente dinámica, como asignar memoria). Así que la expresión throw que se refiere a un símbolo indefinido no se utilizará durante las invocaciones en tiempo de compilación (porque eso fallaría en la compilación) y no se puede usar en tiempo de ejecución, porque el símbolo indefinido causa un error de enlazador.

Debido a que el símbolo indefinido no es "odr-used" en las invocaciones en tiempo de compilación de la función, en la práctica el compilador no creará una referencia al símbolo, por lo que está bien que sea indefinido.

¿Es eso útil? Está demostrando cómo hacerlo, no necesariamente diciendo que es una buena idea o ampliamente útil. Si usted tiene la necesidad de hacerlo por alguna razón, entonces su técnica podría resolver su problema. Si no lo necesitas, no tienes que preocuparte por ello.

Una razón por la que podría ser útil es cuando la versión en tiempo de compilación de alguna operación no es tan eficiente como podría ser. Hay restricciones en el tipo de expresiones permitidas en una función constexpr (especialmente en C++11, algunas restricciones fueron eliminadas en C++14). Por lo que puede tener dos versiones de una función para realizar un cálculo, uno que es óptimo, pero utiliza expresiones que no están permitidos en una función constexpr, y uno que es una función constexpr válida, pero se desempeñaría mal si se llama en tiempo de ejecución. Podría envenenar el subóptimo para asegurarse de que nunca se use para llamadas en tiempo de ejecución, asegurando que la versión más eficiente (no constexpr) se use para llamadas en tiempo de ejecución.

N.B. El rendimiento de una función constexpr utilizada en tiempo de compilación es no es realmente importante, porque no tiene sobrecarga de tiempo de ejecución de todos modos. Podría ralentizar su compilación haciendo que el compilador haga un trabajo adicional, pero no tendrá ningún costo de rendimiento en tiempo de ejecución.

 103
Author: Jonathan Wakely,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-27 21:09:58

'Poisoning' un identificador significa que cualquier referencia al identificador después del 'poisoning' es un error del compilador. Esta técnica se puede utilizar, por ejemplo, para la obsolescencia dura (la función ESTÁ obsoleta, nunca la use!).

En GCC tradicionalmente había un pragma para esto: #pragma GCC poison.

 17
Author: SergeyA,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-27 20:52:01