Nombres representativos
Las funciones, los datos y los objetos de los programas C y C++ se representan internamente con sus nombres representativos. Un nombre representativo es una cadena codificada creada por el compilador durante la compilación de una definición de función, datos u objeto. Registra las convenciones de llamada, los tipos, los parámetros de función y otra información junto con el nombre. Esta representación de nombre, también conocida como decoración de nombre, facilita que el enlazador encuentre las funciones y los objetos correctos al vincular un ejecutable.
Las convenciones de nomenclatura decorada han cambiado en varias versiones de Visual Studio, y también pueden ser diferentes en arquitecturas de destino distintas. Para vincular correctamente con los archivos de origen creados mediante Visual Studio, las bibliotecas y los archivos DLL de C++ y C se deberían compilar mediante el mismo conjunto de herramientas del compilador, las mismas marcas y la misma arquitectura de destino.
Nota:
Las bibliotecas compiladas por Visual Studio 2015 o posteriores se pueden consumir por aplicaciones compiladas con versiones posteriores de Visual Studio a través de Visual Studio 2022. Para obtener más información, consulte Compatibilidad binaria de C++ entre versiones de Visual Studio.
Uso de nombres decorados
Normalmente, no es necesario saber el nombre representativo para escribir código que se compile y se vincule correctamente. Los nombres representativos son un detalle de implementación interno del compilador y el enlazador. En general, las herramientas tratan el nombre en su formato no representativo. Sin embargo, a veces es necesario un nombre representativo cuando se especifica un nombre de función para el enlazador y otras herramientas. Por ejemplo, para que coincida con funciones de C++ sobrecargadas, miembros de espacios de nombres, constructores de clase, destructores y funciones de miembro especiales, se debe especificar el nombre representativo. Para obtener más detalles sobre las marcas de opción y otras situaciones que necesitan nombres representativos, consulte la documentación de las herramientas y opciones que esté usando.
Si cambia el nombre de la función, la clase, la convención de llamada, el tipo de valor devuelto o cualquier otro parámetro, también cambia el nombre representativo. En este caso, debe obtener el nuevo nombre representativo y usarlo en lugar del nombre anterior en todos los lugares en los que se haya especificado.
La decoración de nombres también es importante cuando se vincula a código escrito en otros lenguajes de programación o con otros compiladores. Diferentes compiladores usan convenciones de decoración de nombres distintas. Cuando se vincula una aplicación ejecutable con el código escrito en otro idioma, se debe tener especial cuidado para que los nombres importados y exportados y las convenciones de llamada coincidan. El código de lenguaje de ensamblado debe usar nombres representativos de MSVC y convenciones de llamada para vincular al código fuente escrito con MSVC.
Formato de un nombre decorado en C++
El nombre representativo para una función de C++ contiene la información siguiente:
Nombre de función.
La clase de la que es miembro la función, si se trata de una función miembro. La representación puede incluir la clase que contiene la clase que contiene la función, y así sucesivamente.
El espacio de nombres al que pertenece la función, si forma parte de un espacio de nombres.
Tipos de los parámetros de las funciones.
Convención de llamada.
Tipo de valor devuelto de la función.
Un elemento específico del destino opcional. En los objetos ARM64EC, se inserta una etiqueta
$$h
en el nombre.
Los nombres de función y de clase están codificados en el nombre representativo. El resto del nombre representativo es un código que tiene significado interno solo para el compilador y el enlazador. Aquí tiene algunos ejemplos de nombres de C++ representativo y no representativo.
Nombre no representativo | Nombre representativo |
---|---|
int a(char){int i=3;return i;}; |
?a@@YAHD@Z |
void __stdcall b::c(float){}; |
?c@b@@AAGXM@Z |
Formato de un nombre decorado en C
El formato de decoración para una función de C depende de la convención de llamada usada en su declaración, tal como se muestra en la tabla siguiente. Es también el formato de representación que se usa cuando el código de C++ se declara para que contenga vinculación de extern "C"
. La convención de llamada predeterminada es __cdecl
. En un entorno de 64 bits, las funciones C o extern "C"
solo se decoran al usar la convención de llamada __vectorcall
.
Convención de llamada | Decoración |
---|---|
__cdecl |
Guion bajo inicial (_ ) |
__stdcall |
Guion bajo inicial (_ ) y símbolo de arroba final (@ ) seguidos del número de bytes de la lista de parámetros en formato decimal |
__fastcall |
Símbolos de arroba inicial y final (@ ) seguidos por un número decimal que representa el número de bytes de la lista de parámetros |
__vectorcall |
Dos símbolos de arroba finales (@@ ) seguidos por un número decimal de bytes de la lista de parámetros |
Para las funciones ARM64EC con vinculación de C (si se compilan como C o mediante extern "C"
), se antepone un #
al nombre representativo.
Ver nombres representativos
Puede obtener el formato representativo del nombre de un símbolo después de compilar el archivo de origen que contiene el prototipo o la definición de la función, los datos o el objeto. Para examinar los nombres representativos del programa, puede usar uno de los métodos siguientes:
Para usar una lista para ver nombres representativos
Genere un listado compilando el archivo de origen que contiene el prototipo o la definición de la función, los datos o el objeto con la opción del compilador
/FA
(Tipo de archivo de listas) establecida en ensamblado con código fuente (/FAs
).Por ejemplo, escriba
cl /c /FAs example.cpp
en un símbolo del sistema para desarrolladores para generar un archivo de listas,example.asm
.En el archivo de listas resultante, encuentre la línea que empieza por
PUBLIC
y termina con un punto y coma (;
) seguido del nombre no representativo de la función o los datos. El símbolo situado entrePUBLIC
y el punto y coma es el nombre representativo.
Para usar DUMPBIN para ver nombres representativos
Para ver los símbolos exportados en un archivo OBJ o LIB, escriba
dumpbin /exports <obj-or-lib-file>
en un símbolo del sistema para desarrolladores.Para encontrar el formato representativo de un símbolo, busque el nombre no representativo entre paréntesis. El nombre representativo está en la misma línea, delante del nombre no representativo.
Visualización de nombres sin codificar
Puede usar undname.exe para convertir un nombre representativo a su formato no representativo. En este ejemplo se muestra cómo funciona:
C:\>undname ?func1@a@@AAEXH@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.
Undecoration of :- "?func1@a@@AAEXH@Z"
is :- "private: void __thiscall a::func1(int)"
Consulte también
Herramientas de generación MSVC adicionales
Uso de extern
para especificar la vinculación