compiler compilar compilador como c++ gcc ld

compilar - ¿Qué es una "función clave" de C++ como la describe el oro?



gcc linux (2)

Por favor, no responda la pregunta "¿Cómo resuelvo este mensaje de error?"

En el mensaje de error proporcionado por el oro:

/usr/bin/ld.gold: the vtable symbol may be undefined because the class is missing its key function

¿Qué es una key function ? Encuentro una referencia a él en la página de manual de GCC para los atributos de función en la sección dllimport . El texto relevante lee:

En el destino de SH Symbian OS, el atributo dllimport también tiene otro efecto (sic): puede provocar que la información de tipo vtable y de tiempo de ejecución para una clase se exporte. Esto sucede cuando la clase tiene un constructor dllimport''ed o una función virtual no pura, no en línea y, para cualquiera de estas dos condiciones, la clase también tiene un constructor o destructor en línea y tiene una función clave que se define en el unidad de traducción actual.

De esto saco que hay una función distinta de los constructores o destructores, requerida bajo ciertas condiciones, cuando se usa el atributo dllimport , en el sistema operativo Symbian. Interesante, pero estoy compilando para Linux en Linux, y grep -r dllimport no revela nada. Así que este párrafo no se aplica.

(FWIW, el problema se deriva (en este caso) de un destructor indefinido, pero tanto la documentación como la salida del enlazador hacen un gran esfuerzo para distinguir una "función clave" de un destructor. Para otros tipos de símbolos faltantes, el enlazador deletrea la nombre del símbolo que falta.)

Entonces, ¿qué es realmente una key function ?


(moviendo / expandiendo desde el comentario)

Como explicó @navylover, la función clave es la primera función virtual no en línea definida en la clase; es importante porque es utilizado por el compilador como un marcador convencional para decidir en qué TU se debe emitir el vtable (ya que debe emitirse solo una vez): cualquiera que sea la definición de la función clave, el módulo de objeto correspondiente contendrá el TU. Vtable también.

De ello se deduce que, si ninguna TU define la función clave (por ejemplo, porque olvidó definirla), el vtable nunca se emitirá, de ahí el error.

Gold está intentando indicarle en la dirección correcta: si falta el vtable, probablemente se deba a que también falta la función clave (de nuevo, ya sea porque no definió u olvidó vincular su módulo), aunque puede que no. aparecer explícitamente como una referencia no definida (lo que podría ponerlo en el camino correcto) porque en el resto del código nadie lo invoca directamente 1 , como en este ejemplo:

struct Test { virtual void foo(); virtual int bar() { return 0; } }; int main() { Test t; t.bar(); return 0; }

[matteo@teolapkubuntu /tmp]$ g++ -fuse-ld=gold keyf.cpp /tmp/ccduMsT3.o:keyf.cpp:function main: error: undefined reference to ''vtable for Test'' /usr/bin/ld.gold: the vtable symbol may be undefined because the class is missing its key function

Compare esto con el GNU ld regular, que solo dice

[matteo@teolapkubuntu /tmp]$ g++ keyf.cpp /tmp/ccUr3Xyi.o: In function `main'': keyf.cpp:(.text+0x1a): undefined reference to `vtable for Test'' collect2: error: ld returned 1 exit status

¿OK y eso qué? No es como si tuviera que definir explícitamente vtables, así que definitivamente no es obvio dónde debería empezar a buscar para corregir este tipo de error.

  1. Sin embargo, una función de este tipo puede invocarse indirectamente a través de un puntero a la clase base, y el vinculador aún mostrará solo la referencia indefinida a vtable y no a la función, ya que la única referencia a la función en este caso estaría en vtable, que falta

La función clave se define como la primera función virtual no en línea declarada en la clase. El wiki oficial de gcc al respecto está here .