¿Hay algún caso en el que la falta de un #include
se rompa el software en tiempo de ejecución, mientras que la compilación aún continúa?
En otras palabras, ¿es posible que
#include "some/code.h"
complexLogic();
cleverAlgorithms();
y
complexLogic();
cleverAlgorithms();
¿ambos construirían con éxito, pero se comportarían de manera diferente?
#include
d.#include <vld.h>
en una posición estratégica en su código. Eliminar o agregar ese encabezado de VLD no "interrumpe" el programa, pero afecta significativamente el comportamiento del tiempo de ejecución. He visto a VLD desacelerar un programa hasta el punto de que se volvió inutilizable.Respuestas:
Sí, es perfectamente posible. Estoy seguro de que hay muchas formas, pero supongamos que el archivo de inclusión contiene una definición de variable global que se denomina constructor. En el primer caso, el constructor se ejecutaría, y en el segundo no.
Poner una definición de variable global en un archivo de encabezado es un estilo pobre, pero es posible.
fuente
<iostream>
en la biblioteca estándar hace precisamente esto; si alguna unidad de traducción incluye,<iostream>
entonces elstd::ios_base::Init
objeto estático se construirá al inicio del programa, inicializando las secuencias de caracteresstd::cout
, etc., de lo contrario no lo hará.Si, eso es posible.
Todo lo que concierne a
#include
s sucede en tiempo de compilación. Pero las cosas en tiempo de compilación pueden cambiar el comportamiento en tiempo de ejecución, por supuesto:some/code.h
:entonces
Con la
#include
resolución de sobrecarga encuentra el más apropiadofoo(int)
y por lo tanto se imprime1
en lugar de2
. Además, comoFOO
está definido, también imprimeFOO
.Son solo dos ejemplos (no relacionados) que me vinieron a la mente de inmediato, y estoy seguro de que hay muchos más.
fuente
Solo para señalar el caso trivial, las directivas de precompilador:
Y entonces
Es patológico, tal vez, pero he tenido un caso relacionado:
Parece inocuo Intenta llamar
std::max
. Sin embargo, windows.h define max para serSi esto fuera así
std::max
, sería una llamada de función normal que evalúa f () una vez y g () una vez. Pero con windows.h allí, ahora evalúa f () o g () dos veces: una durante la comparación y otra para obtener el valor de retorno. Si f () o g () no fue idempotente, esto puede causar problemas. Por ejemplo, si uno de ellos es un contador que devuelve un número diferente cada vez ...fuente
using namespace std;
y usastd::max(f(),g());
, el compilador detectará el problema (con un mensaje oscuro, pero al menos apuntando al sitio de la llamada).Es posible que falte una especialización de plantilla.
fuente
Incompatibilidad binaria, acceder a un miembro o, lo que es peor, llamar a una función de la clase incorrecta:
Una función lo usa, y está bien:
Trayendo otra versión de la clase:
Usando funciones en main, la segunda definición cambia la definición de clase. Conduce a incompatibilidad binaria y simplemente se bloquea en tiempo de ejecución. Y solucione el problema eliminando la primera inclusión en main.cpp:
Ninguna de las variantes genera un error de tiempo de compilación o enlace.
La situación viceversa, al agregar un include, corrige el bloqueo:
Estas situaciones son aún más difíciles cuando se corrige un error en una versión antigua del programa o cuando se usa una biblioteca externa / dll / objeto compartido. Es por eso que a veces se deben seguir las reglas de compatibilidad binaria hacia atrás.
fuente
Quiero señalar que el problema también existe en C.
Puede decirle al compilador que una función usa alguna convención de llamada. Si no lo hace, el compilador tendrá que adivinar que usa el predeterminado, a diferencia de C ++, donde el compilador puede negarse a compilarlo.
Por ejemplo,
main.c
foo.c
En Linux en x86-64, mi salida es
Si omite el prototipo aquí, el compilador asume que tiene
Y la convención para listas de argumentos no especificadas requiere que
float
se convierta paradouble
que se pase. Entonces, aunque di1.0f
, el compilador lo convierte1.0d
para pasarlofoo
. Y de acuerdo con el Suplemento del procesador de arquitectura AMD64 de la interfaz binaria de la aplicación System V,double
se pasa en los 64 bits menos significativosxmm0
. Perofoo
espera un flotante, y lo lee de los 32 bits menos significativos dexmm0
, y obtiene 0.fuente