2010-07-25 9 views
39

Quiero forzar que una pequeña función no se compile como función en línea, incluso si es muy simple. Creo que esto es útil para la depuración. ¿Hay alguna palabra clave para hacer esto?¿Es posible forzar que una función no esté en línea?

+14

El depurador puede manejar perfectamente las funciones en línea. No hay necesidad de evitar la inflación debido a eso. – jalf

+8

No realmente. Excelente manera de colgar el depurador durante muchos minutos mientras establece miles de puntos de interrupción. –

+7

Al pasar a través del código optimizado (que básicamente tiene que hacer a nivel de lenguaje ensamblador) a veces es agradable ver llamadas a funciones para que pueda seguir donde se encuentra y pasarlas de una vez, ya que la vista del compilador "simple" puede no ser tuyo. (El depurador puede funcionar bien con todo esto, pero es el operador de la computadora el que realmente tiene que hacer el trabajo ...) –

Respuesta

42

En Visual Studio 2010, __declspec(noinline) indica al compilador que no inline una función miembro en particular, por ejemplo:

class X { 
    __declspec(noinline) int member_func() { 
      return 0; 
    } 
}; 

edición: Además, al compilar con /clr, funciona con atributos de seguridad nunca se inline (de nuevo, esto es específico de VS 2010).

No creo que sea útil en la depuración.

+0

La documentación dice que es solo para funciones miembro: https://msdn.microsoft.com/en-us/library/kxybs02x.aspx. ¿Hay alguna manera de hacer que una función autónoma no esté en línea? –

2

Muchos compiladores pueden realizar en línea la unidad de traducción cruzada. Visual Studio lo ha tenido durante cinco años y creo que ahora GCC puede hacerlo, especialmente desde que el OP etiquetado como Visual C++, es una apuesta justa que su compilador puede hacer frente.

La forma más sencilla de hacerlo es tomar la dirección de la función y luego hacer algo que no tenga sentido, como llamarla o pasarla a una función de biblioteca externa/SO. El compilador no puede alinear ese tipo de función.

Por qué alguna vez querrías, IDK.

@comments:

Si el OP srsly, srsly necesita esto, entonces podría compilar como un lib y estáticamente enlazar con él.

+7

Si bien tomar la dirección de una función requiere que el compilador proporcione una versión no en línea de la misma, no creo que se requiera para no incluirla en otros lugares. – sbi

+2

Eso no impide que incluya una función. Como sbi correctamente señaló, solo producirá una versión no en línea. – wheaties

+0

Estoy bastante seguro de que la documentación de VC++ dice que no alineará ninguna función en la que se tome su dirección. Sin embargo, ciertamente no puede moverlo entre unidades de traducción, y si no puede tomar su dirección, entonces la única manera de estar seguro es compilarlo en una lib externa. – Puppy

-6

¿Es posible forzar que una función no esté en línea?

Ni siquiera intentaré responder esa pregunta, porque es irrelevante preocuparse por esto excepto por las dos razones que se detallan a continuación.

Inlining básicamente es

  1. una optimización que es casi transparente para que
  2. una manera de permitir que las funciones que se definirán en las cabeceras sin obtener errores de definición multpile

(Algunos podrían cambiar el orden de estos dos, pero me atengo a la orden tradicional.)

A menos que sea A) es absolutamente necesario define una función en algún encabezado o B) está perfilando y optimizando una pieza de código y sabe mejor que el compilador lo que debe incluirse y lo que no debería ser, la inserción no debería preocuparle.
Sin duda no debería ser una preocupación debido a la depuración. Su depurador debe (y en el caso de VC también lo hace) encargarse de eso por usted.

+14

@sbi Soy uno de los downvoters. Una función real tiene un símbolo en el código objeto, ofrece varios beneficios sobre una paz de código en línea. Puede rastrearlos desde un depurador o un analizador de código dinámico. Con un generador de perfiles puede saber la cantidad exacta de tiempo dedicado a la función, es difícil cuando la paz del código se fusiona en otra paz de código más grande. Puede cambiar el nombre dinámicamente de la función, o incluso sustituir esta función por otra en el tiempo de ejecución. – Ben

+0

@Ben: la depuración generalmente tiene lugar en el código creado para la depuración, y eso no debería tener funciones en blanco de todos modos. Para compilaciones de versiones, la alineación es solo una de las muchas distorsiones perturbadoras que el optimizador hace a su código. Y no delimitar una función para perfilar parece _absurd_, por decirlo suavemente. (Se trata de los analizadores de códigos dinámicos más comunes, ¿qué más hay?), Lo que deja el cambio de nombre de una función en tiempo de ejecución, lo que parece un concepto extraño, a menos que haga referencia al enlace tardío a libs cargados dinámicamente (.so, .dll). Ese es el único caso que puedo ver para "no" querer alinear una función. – sbi

+3

@sbi: No es absurdo, no puede evaluar el costo de una función en línea. Por analizador de código dinámico me refiero a herramientas como valgrind purificar o asegurar ++. Sí, estaba pensando en un enlace o reenlazamiento tardío, lo uso en algún momento siguiendo el propósito. De todos modos, no sé qué quería Thomson, pero puede no ser irrelevante para él, por eso he votado negativamente. – Ben

1

Puede dividir la implementación de la clase entre un encabezado y un archivo cpp. si coloca la función fuera de la definición de clase, su pequeña función no estará en línea.

+6

En algunos, pero no en todos los compiladores, esto funcionará. OTOH Tengo un problema con quien lo rechazó y ni siquiera dejé un comentario explicando por qué. –

10

Recuerde que la alineación es relevante en el sitio de la llamada a la función , la misma función se puede insertar en algunas situaciones y no en otra.

Si su función es visible fuera de la unidad de compilación a continuación, incluso si se trata de inline en todo los lugares actuales se consume, el cuerpo de la función todavía debe estar disponible para cualquier persona que quiera llamarlo posteriormente (mediante la vinculación con el archivo objeto).

Para que un sitio de llamada no esté en línea, puede usar un puntero a una función.

void (*f_ptr)(int); // pointer to function 
volatile bool useMe = true; // disallow optimizations 
if (useMe) 
    f_ptr = myFunc; 
else 
    f_ptr = useOtherFunc; 

f_ptr(42); // this will not be inlined 
35

__declspec(noinline) para VC++. A diferencia de la página man, esto parece funcionar para funciones independientes, y no creo haberlo usado nunca para una función miembro. Puede -aunque tenga en cuenta que nunca lo he hecho- querer considerar jugar con los indicadores de optimización también, de modo que solo las funciones inline se consideren para la alineación, aunque, por supuesto, esto tiene un efecto global y es posible que no sea lo que usted desea.

__attribute__((noinline)) para gcc (y una serie de compiladores menos comunes que admiten la sintaxis del atributo gcc). Debo admitir que no creo haber usado esto alguna vez, pero parece estar allí.

(Por supuesto, estos dos estilos de anotación van en diferentes lugares, por lo que es un poco molesto para construir código que es aceptable para ambos.)

No estoy seguro de cómo cualquiera de éstos interactúan con el inline C++ palabra clave; Solo los he usado para depurar (cuando solo quiero que una función en particular que no esté en línea no esté en línea después de la optimización) o cuando examino el código generado (y me confundo porque algo aleatorio está en línea).

+1

funciona también para funciones de miembros. Una nota interesante a tomar es que parece hacer llamadas no en línea para contener funciones también (aunque de otra manera estarían en línea) - VS 2012 – Ghita

+0

cómo verificar mediante cmake qué compilador utilizó: vC++ o gcc y hacer definir 'noinline'? – Andreyua

4

Simple: no permita que el compilador vea la definición de la función. Entonces no puede ser inline. Por supuesto, eso solo funciona si es su código.

Cuando se trata de depurar código de terceros ... sí, esto sería útil, especialmente si se puede borrar el código de terceros desde lejos. Cualquier persona que haya depurado el código que contiene mucha desreferencia compartida comparte lo que estoy diciendo.

1

Si es una función miembro de una clase, hágalo virtual.

+2

No necesariamente funcionará; si el método se puede desvirtualizar, aún puede estar en línea. – Alice

Cuestiones relacionadas