2009-08-04 15 views
18

Estoy usando la inicialización estática para facilitar el proceso de registrar algunas clases con una fábrica en C++. Lamentablemente, creo que el compilador está optimizando los objetos 'no utilizados' que están destinados a hacer el trabajo útil en sus constructores. ¿Hay alguna manera de decirle al compilador que no optimice una variable global?¿Cómo evito que se compilen mis variables globales 'no utilizadas'?

class SomeClass { 
    public: 
     SomeClass() { 
      /* do something useful */ 
     } 
}; 

SomeClass instance; 

Mi punto de interrupción en el constructor de SomeClass no recibe ningún golpe. En mi código actual, SomeClass está en un archivo de cabecera y la instancia está en un archivo fuente, más o menos solo.

EDITAR: como adivinó KJAWolf, este código se compila realmente en una lib estática, no el ejecutable. Su propósito es registrar algunos tipos también proporcionados por la lib estática con una lista estática de tipos y sus creadores, para que una fábrica pueda leer en la construcción. Como estos tipos se proporcionan con la lib, no se desea agregar este código al ejecutable.

También descubrí que al mover el código a otro archivo fuente que contiene otro código existente, funciona bien. Parece que tener un archivo que consiste puramente en estos objetos globales es lo que está causando el problema. Es como si esa unidad de traducción fuera ignorada por completo.

+1

¿Es su archivo fuente parte del ejecutable, o es parte de una biblioteca estática? – KJAWolf

+0

Aha, buen trabajo de adivinación. En realidad, el archivo fuente es parte de una lib estática. ¿Eso causaría un problema? Estoy 80% seguro de haber hecho exactamente lo mismo antes y funcionó. –

+0

tuve el mismo problema: http://stackoverflow.com/questions/599035/force-visual-studio-to-link-all-symbols-in-a-lib-file – Lodle

Respuesta

34

El compilador no puede optimizar los objetos globales.
Incluso si nunca se utilizan.

Algo más está sucediendo en su código.
Ahora, si creó una biblioteca estática con su objeto global y ese objeto global no está referenciado desde el ejecutable, el vinculador no lo arrastrará al ejecutable.

+9

He votado a favor de esto porque creo que es la única respuesta que identifica el problema real; Como dice el que pregunta "Parece que tener un archivo que consista puramente en estos objetos globales es lo que está causando el problema. Es como si la unidad de traducción hubiera sido ignorada por completo". La unidad de traducción se ignora en el sentido de que el enlazador la omite porque está en una biblioteca. Si un objeto está en una biblioteca y no lo llama nada en la aplicación, se omite, esa es la idea de las librerías. –

+0

Ídem, que golpeó el clavo en la cabeza. Subí la respuesta de Pavel también porque también lo hizo bien :) –

+1

Entonces, ¿cómo lo arreglamos? – Sam

5

El compilador nunca debe optimizar tales variables globales; si lo hace, simplemente se rompe.

+3

Si el compilador no puede detectar el uso de global, puede omitirlos. GCC (G ++ en este contexto) puede omitir algunas variables; por ejemplo, los trucos anteriores de "incrustar una versión en el archivo de objeto" no funcionan con GCC moderno; el valor estático del archivo se detecta como no utilizado y optimizado para el objeto archivo. –

+0

file static! = Global –

+0

Si tienen un cnstructor, existe un efecto secundario potencial por el uso del constructor. Como gcc no realiza análisis de funciones cruzadas, nunca podrá detectar el potencial de un efecto secundario y, por lo tanto, no se le permitirá eliminarlo. –

2

Para construir fuera de Arthur Ulfeldt, volátil le dice al compilador que esta variable puede cambiar fuera del conocimiento del compilador. Lo he usado para poner una declaración para permitir que el depurador establezca un punto de interrupción. También es útil para registros de hardware que pueden cambiar en función del entorno o que necesitan una secuencia especial. es decir, el registro de recepción del puerto serie y ciertos registros de vigilancia.

+1

No, simplemente dice el compilador que no debe almacenar en caché un valor previamente leído de la variable. –

+0

Es útil para el subprocesamiento :) – Partial

+2

volátil es fall para multithreading :( – paulm

1

podría utilizar

 
#pragma optimize off 
int globalVar 
#pragma optimize on 

pero no sé si es que sólo funciona en Visual Studio (http://msdn.microsoft.com/en-us/library/chh3fb0k(VS.80).aspx).

También podría decir que el compilador no optimizar en absoluto, especialmente si usted está depuración ...

+0

Esto no es compatible con todos los compiladores/IDE – Partial

+0

pero me hubiera gustado! – radsdau

+0

En Visual Studio la sintaxis es #pragma optimize ("", off) pero para mí no impide que la variable global se elimine en una biblioteca estática. – gast128

0

¿Está utilizando gcc con gdb? Hubo un problema en el pasado donde gdb no podía establecer con precisión los puntos de interrupción en los constructores.

Además, ¿está utilizando un nivel de optimización que permite al compilador aplicar métodos en línea en la definición de la clase.

-2

¿Qué le parece usar la palabra clave volátil? Evitará que el compilador optimice demasiado.

0

Tengo la misma configuración & problema en VS2008. Encontré que si declara que su clase es dllexport, no se optimizará.

class __declspec(dllexport) Cxxx 
{ 
. 
} 

Sin embargo, esto genera una gran cantidad de advertencias en mi caso porque debo declarar todas clases que se utilizan en esta clase también como dllexport.

Todas las optimizaciones están desactivadas (en modo de depuración), aún esto está optimizado. También volatil/pragma optimize off. En la variable global creada de esta clase (en el mismo archivo cpp) etc. no funciona.

Acabo de descubrir que dllexport requiere al menos incluir archivos de encabezado de estas clases en algún otro archivo cpp desde exe a work! Entonces, la única opción es agregar un archivo con llamadas a algunos miembros estáticos para cada clase, y agregar este archivo a todos los proyectos que usen estas clases.

1

Se puede forzar que un objeto (su lista de tipos) tira algunos otros objetos con ella por que une parcialmente ellos antes de la construcción de la lib estática completa.

Con GNU linker:

ld -Ur -o TypeBundle.o type1.o type2.o type3.o static_list.o 
ld -static -o MyStaticLib.a type_bundle.o other_object.o another_object.o ... 

Por lo tanto, cada vez que la lista estática es referenciado por código usando la biblioteca, el objeto completo "TypeBundle.o" obtendrá vinculado en el binario resultante, incluyendo type1.o, tipo2 .o, y type3.o.

Mientras que en él, verifique el significado de "-Ur" en the manual.

Cuestiones relacionadas