Pregunta

Me he encontrado __stdcall mucho en estos días.

MSDN no explica muy claramente lo que significa realmente, cuándo y por qué se debe utilizar, en todo caso.

I apreciaría si alguien sería proporcionar una explicación, preferiblemente con uno o dos ejemplos.

¿Fue útil?

Solución

Todas las funciones en C / C ++ tienen una convención de llamada particular. El punto de una convención de llamada es establecer cómo se pasa de datos entre el llamante y el usuario llamado y quién es responsable de las operaciones, tales como la limpieza de la pila de llamadas.

Las convenciones de llamada más populares en las ventanas son

  • __stdcall, empuja parámetros en la pila, en el orden inverso (derecha a izquierda)
  • __cdecl, empuja parámetros en la pila, en el orden inverso (derecha a izquierda)
  • __clrcall, los parámetros de carga en la pila expresión CLR en orden (de izquierda a derecha).
  • __fastcall, almacenados en los registros y, a continuación empujado en la pila
  • __thiscall, Empujado en la pila; este puntero almacenado en ECX

La adición de este especificador a la declaración de la función esencialmente le dice al compilador que desea que esta función particular que tiene esta convención de llamada particular.

Las convenciones de llamada se documentan aquí

Raymond Chen también hizo una larga serie en la historia de las diversas convenciones de llamada (5 partes) a partir aquí.

Otros consejos

Tradicionalmente, las llamadas a funciones C se hacen con la persona que llama empujando algunos parámetros en la pila, llamar a la función, y luego hacer estallar la pila para limpiar esos argumentos empujadas.

/* example of __cdecl */
push arg1
push arg2
push arg3
call function
add sp,12 // effectively "pop; pop; pop"

Nota:. La convención por defecto - se muestra más arriba - se conoce como __cdecl

La otra convención más popular es __stdcall. En ella los parámetros son empujados de nuevo por la persona que llama, pero la pila se limpia por el destinatario de la llamada. Es la convención estándar para las funciones de la API de Win32 (según la definición de la macro en WINAPI), y también es a veces llamado el "Pascal" convención de llamada.

/* example of __stdcall */
push arg1 
push arg2 
push arg3 
call function // no stack cleanup - callee does this

Esto parece un detalle técnico de poca importancia, pero si hay un desacuerdo sobre cómo se gestiona la pila entre la llama y el destinatario de la llamada, la pila será destruido de una manera que es poco probable que se recuperarán. Desde __stdcall qué pila de limpieza, la (muy pequeña) código para realizar esta tarea se encuentra en un solo lugar, en vez de ser duplicado en cada persona que llama como lo es en __cdecl. Esto hace que el código muy ligeramente más pequeño, aunque el impacto de tamaño sólo es visible en grandes programas.

variadic funciones como printf () son casi imposibles de estar bien con __stdcall, porque sólo la persona que llama sabe realmente cuántos argumentos se pasó el fin de limpiarlos. El destinatario de la llamada puede hacer que algunas buenas conjeturas (por ejemplo, al observar una cadena de formato), pero la limpieza de la pila tendría que ser determinada por la lógica real de la función, no el mecanismo de llamadas de convención misma. Por tanto, sólo es compatible con las funciones __cdecl variadic de modo que la persona que llama puede hacer la limpieza.

decoraciones Enlazador nombre del símbolo: Como se mencionó en un punto anterior, llamar a una función con la convención "mal" puede ser desastroso, por lo que Microsoft tiene un mecanismo para evitar que esto suceda. Funciona bien, aunque puede ser enloquecedor si uno no sabe cuáles son las razones. Ellos han optado por resolver este codificando la convención de llamada en los nombres de las funciones de bajo nivel con caracteres adicionales (que a menudo son llamados "decoraciones"), y estos son tratados como nombres no relacionados por el enlazador. La convención de llamada por defecto es __cdecl, pero cada uno puede ser solicitado de manera explícita con el modificador / G? parámetro para el compilador.

__ cdecl (CL / Gd ...)

Todos los nombres de las funciones de este tipo tienen el prefijo con un guión y el número de parámetros en realidad no importa, porque la persona que llama es responsable de la configuración y limpieza pila pila. Es posible que una persona que llama y el destinatario de la llamada a ser confundidos sobre el número de parámetros que se le pasan, pero al menos la disciplina pila se mantiene correctamente.

__ stdcall (cl / Gz ...)

Estos nombres de función se prefijan con un guión y anexan con @ más el número de bytes de parámetros pasados. Por este mecanismo, no es posible llamar a una función con el tipo "malo", o incluso con el número de parámetros falsos.

__ fastcall (cl / Gr ...)

Estos nombres de las funciones comienzan con un signo @ y se añade el sufijo con el recuento @parameter, al igual que __stdcall.

Ejemplos:

Declaration                        ----------------------->    decorated name


void __cdecl foo(void);            ----------------------->    _foo

void __cdecl foo(int a);           ----------------------->    _foo

void __cdecl foo(int a, int b);    ----------------------->    _foo

void __stdcall foo(void);          ----------------------->    _foo@0

void __stdcall foo(int a);         ----------------------->    _foo@4

void __stdcall foo(int a, int b);  ----------------------->    _foo@8

void __fastcall foo(void);         ----------------------->    @foo@0

void __fastcall foo(int a);        ----------------------->    @foo@4

void __fastcall foo(int a, int b); ----------------------->    @foo@8

__ stdcall es una convención de llamada:. Una forma de determinar cómo se transmiten los parámetros de una función (en la pila o en los registros) y quién es responsable de la limpieza después de la función devuelve (el llamante o el llamado)

Raymond Chen escribió un blog rel="noreferrer"> , y hay un buen artículo CodeProject también.

En su mayor parte, que no debería tener que preocuparse de ellos. El único caso en el que se debe decir, si usted está llamando a una función de biblioteca que utiliza algo distinto al predeterminado -. De lo contrario el compilador generará un código incorrecto y su programa probablemente se bloqueará

Desafortunadamente, no hay una respuesta fácil para cuándo usarlo y cuándo no.

__ stdcall significa que los argumentos a una función se insertan en la pila de la primera a la última. Esto es en contraposición a __cdecl, lo que significa que los argumentos son empujados desde el último al primero, y __fastcall, lo que sitúa los primeros cuatro (creo) argumentos en los registros, y el resto van a la pila.

Sólo tiene que saber lo que espera que el destinatario de la llamada, o si usted está escribiendo una biblioteca, lo que es probable que las personas que llaman esperas, y asegúrese de documentar su convención elegida.

Se especifica una convención de llamada para una función. Una convención de llamada es un conjunto de reglas de cómo se pasan los parámetros de una función: en qué orden, por dirección o por copia, que es limpiar los parámetros (o destinatario de la llamada del llamador), etc.

__ stdcall denota una convención de llamada (ver este PDF por algunos detalles). Esto significa que especifica cómo los argumentos de funciones se empujan y se metió de la pila, y quién es responsable.

__ stdcall es sólo una de varias convenciones de llamada, y se utiliza en todo el WINAPI. Debe usarlo si proporciona punteros a funciones como las devoluciones de llamada para algunas de esas funciones. En general, no es necesario para denotar cualquier convención de llamada específico en su código, pero sólo tiene que utilizar por defecto del compilador, excepto en el caso señalado anteriormente (que proporciona devoluciones de llamada a código de tercera parte).

Esto es una convención de llamada que necesitan ser llamados adecuadamente las funciones WinAPI. Una convención de llamada es un conjunto de reglas sobre cómo se pasan los parámetros en la función y cómo se transmite el valor de retorno de la función.

Si la persona que llama y el código de llamada utilizan diferentes convenciones se encuentra con un comportamiento indefinido (como como una de aspecto extraño accidente ).

compiladores de C ++ no utilizan __stdcall por defecto - que utilizan otras convenciones. Así que con el fin de llamar a las funciones WinAPI de C ++, tiene que especificar que utilizan __stdcall -. Esto se suele hacer en los archivos de cabecera Windoes SDK y también lo hacen cuando se declara punteros de función

en pocas palabras cuando se llama a la función, que se carga en la pila / register. __stdcall es una convención / forma (argumento de la derecha primero, luego a la izquierda argumento ...), __decl es otra convención que se utiliza para cargar la función en la pila o de registros.

Si los usa se indica al equipo para utilizar de esa manera específica para cargar / descargar la función durante el enlace y por lo tanto no se pueden conseguir una falta de coincidencia / accidente.

De lo contrario la función de destinatario de la llamada y la función de llamada podrían usar diferentes convenciones causando programa se bloquee.

__ stdcall es la convención de llamada utilizado para la función. Esto le dice al compilador de las reglas que se aplican para la creación de la pila, empujando argumentos y conseguir un valor de retorno. Hay una serie de otras convenciones de llamada como __ cdecl , __ thiscall , __ fastcall y __ desnuda .

__ stdcall es la convención de llamada estándar para las llamadas al sistema de Win32.

Más detalles se pueden encontrar en Wikipedia .

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top