Estructura de retorno de C/C++ por valor debajo del capó

3 minutos de lectura

(Esta pregunta es específica para la arquitectura de mi máquina y las convenciones de llamadas, Windows x86_64)

No recuerdo exactamente dónde había leído esto, o si lo había recordado correctamente, pero escuché que, cuando una función debe devolver alguna estructura u objeto por valor, lo rellenará rax (si el objeto puede caber en el ancho de registro de 64 bits) o se le pasa un puntero a donde estaría el objeto resultante (supongo que está asignado en el marco de pila de la función de llamada) en rcxdonde haría toda la inicialización habitual, y luego un mov rax, rcx para el viaje de regreso. Es decir, algo como

extern some_struct create_it(); // implemented in assembly

realmente tendría un parámetro secreto como

extern some_struct create_it(some_struct* secret_param_pointing_to_where_i_will_be);

¿Me sirvió bien la memoria o estoy equivocado? ¿Cómo se devuelven los objetos grandes (es decir, más anchos que el ancho del registro) por valor de las funciones?

  • Omitió un tipo de devolución de su función de ejemplo, cuando desea información sobre lo que se devuelve.

    – Veleta

    21 de agosto de 2016 a las 20:21


  • Parece que estás hablando de optimización del valor de retorno, que es específico de C++. No tengo conocimiento de ninguna característica de este tipo en C.

    – abeto

    21 de agosto de 2016 a las 20:25

  • Realmente depende del compilador de C++ y del nivel de optimizaciones que esté utilizando para su compilación. Hay muchos compiladores de C++ para x86-64 win64.

    – Mike Nakis

    21 de agosto de 2016 a las 20:26


  • @mike: no, lo define la plataforma ABI. Si se permitiera variar entre los niveles de optimización, no podría usar bibliotecas externas. Si pudiera variar entre compiladores, necesitaría diferentes bibliotecas para cada compilador. Esta es la razón por la que se deben definir convenciones de llamada para cada plataforma y, por lo tanto, por la que existen las ABI de plataforma.

    – rico

    21 de agosto de 2016 a las 20:42

  • Si. No solo se aplica al valor devuelto, también a los parámetros. Los detalles exactos son bastante complicados y están mal documentados. Agner Fog hizo el trabajo duro, Capítulo 7 tiene todo lo que te gustaría saber y más.

    -Hans Passant

    21 de agosto de 2016 a las 21:01

  • Utilizar gcc.godbolt.org para ver la salida del compilador para x86, x86-64, ARM, MIPS, PowerPC o AVR, con clang o gcc. Además, podría acortar el ejemplo usando A myA = { b, c, 5, 6, 7, 8, 9, 10}. Y probablemente suelte un par de miembros de la estructura para acortar el asm. Siempre que tenga más de 128 bits, la convención de llamadas x86-64 SysV no lo empaquetará en RDX:RAX.

    – Peter Cordes

    21 de agosto de 2016 a las 21:59

  • Además, el asm sería mucho más fácil de leer si compilara foo con la optimización habilitada. Hacer que se almacene en un local en la pila y luego copiarlo en el puntero de valor de retorno es realmente ruidoso y difícil de seguir si aún no sabe qué es lo que está haciendo.

    – Peter Cordes

    21 ago 2016 a las 22:00

  • Originalmente, este código era un poco más complicado como parte de mí probando su desensamblado, lo edité rápidamente sin cambiar eso, pero tienes razón, aunque es mucho más legible, no haría eso en el desarrollo del código real: ), y estoy de acuerdo contigo, solo quería demostrar que la copia real es lo que sucede debajo del capó @PeterCordes

    – Dr. PriItay

    21 de agosto de 2016 a las 22:01


  • más específicamente, consulte la wiki de etiquetas x86 para obtener enlaces a documentos de ABI que especifican las reglas para cuando una estructura se empaqueta en uno o dos registros, o cuando un puntero se pasa como un primer argumento oculto. Las reglas difieren entre ABI, para 32 y 64 bits. Ver también estructuras en convenciones de llamadas en documentos SO

    – Peter Cordes

    21 de agosto de 2016 a las 20:47

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad