c++ - una - variables globales pdf
¿Cuándo es segura la inicialización de las constantes globales con enlace externo del orden de inicialización estática? (2)
Considere el siguiente ejemplo:
tt.h declara una constante global con enlaces externos
extern int g_TRAGIC;
tt.cpp define g_TRAGIC como sigue
const int g_TRAGIC = 0xF001;
my.cpp quiere usarlo para definir su propia constante global constante
const int g_MAGIC = g_TRAGIC;
Cuando leo el iso-FAQ supongo que esto da como resultado un fiasco de orden de inicialización estática. Sin embargo, las notas iso-FAQ
El fiasco de orden de inicialización estático también puede, en algunos casos, aplicarse a los tipos intrínsecos / incorporados.
¿Qué significa eso en algunos casos? ¿En qué condiciones se guardan y suenan desde SIOF para tipos incorporados / intrínsecos, en particular constantes? ¿O se debe usar Construir en el primer uso del idioma para todas las constantes con enlace externo?
Nota: En el código real no puedo cambiar la definición de g_TRAGIC.
La lectura adicional de iso-FAQ nos da una respuesta.
SIOF sucede si intenta inicializar el tipo incorporado / intrínseco por el valor de retorno de la función constante.
const int g_MAGIC = f(g_TRAGIC);
Los compiladores pueden producir diferentes tipos de código.
Segmento de datos inicializado estático
El compilador emite en una sección de datos un nombre y su valor inicial.
.data
dw myData 6
Esto se inicializa en el momento de la compilación y se define de manera segura a lo largo de la vida del programa.
datos construidos
Otra alternativa es que el compilador reserve algo de espacio para la variable y cree un inicializador / constructor para los datos, y luego llame al constructor justo antes de main
. Con el destructor (si es necesario) realizado atexit
.
class CriticalSection {
CRITICAL_SECTION m_myCS;
public:
CriticalSection() {
InitializeCriticalSection( &m_myCS );
}
~CriticalSection() {
DeleteCriticalSection( & m_myCS );
}
} cs;
conjunto
Algunos datos se pueden realizar en ambas etapas.
struct Data {
bool initialized;
void *(*pMalloc)( size_t size );
} FixMalloc = { true, MyMalloc };
He visto a los compiladores (VS2013) producir código que se inicializa como verdadero en los datos estáticos, pero crea una función para asignar pMalloc
a MyMalloc
en tiempo de ejecución. (Esto se debió a que no había una constante conocida para MyMalloc).
método singleton
SomeClass * GetSomeClass()
{
static SomeClass cls;
return &cls;
}
Este es un orden definido: cuando se llama, pero requiere que un compilador totalmente C++11
sea seguro para subprocesos.
Resumen
Las garantías son: -
- Las estadísticas en la misma unidad de compilación se inicializan de arriba a abajo.
- Las estadísticas están inicializadas de un solo hilo.
- Los singletons tienen orden de construcción definido. Pero no necesariamente hilo seguro.
Las garantías no son:
- Todo un objeto se inicializa al mismo tiempo.
- La inicialización estática tiene un tiempo de ejecución de trabajo.
Antes de llamar a main, tanto sus estadísticas como el tiempo de ejecución de C / C ++ son bootstrapping. Los problemas de orden de construcción también ocurren entre su código y el tiempo de ejecución, por lo que puede construir algunos elementos con constructores complejos que dependen de servicios que no pueden estar disponibles.