Parámetro de estructura dañado en la llamada de función
Frecuentes
Visto 1,646 veces
0
Tengo problemas para rastrear la causa de un comportamiento extraño al pasar una estructura como parámetro.
La estructura en cuestión, structFoo, tiene la siguiente declaración:
typedef struct _structFoo {
int id;
BSTR szDescription;
VARIANT vData;
BOOL bTransient;
} structFoo;
Tengo dos módulos, A y B. El módulo A llama a B::foo( int id, uint filter, structFoo sF ). En A, antes de la llamada, la estructura structFoo se forma correctamente y se llena con datos válidos. Sin embargo, una vez que se realiza la llamada de función a B::foo(), el parámetro structFoo contiene datos basura. Tras un examen más detallado, resulta que la dirección de la estructura copiada se coloca en el campo de identificación y szDescription apunta a la cadena utilizada más recientemente. Los otros parámetros son correctos después de la llamada a la función.
No estoy seguro de la razón de esta desalineación, o lo que sea que esté sucediendo, pero me parece que hasta que se realiza la llamada a la función, todo está en su lugar correcto. Aquí está el desmontaje que conduce a la llamada de función:
0000000006003211 lea rdi,[rsp+230h]
0000000006003219 lea rsi,[sAttPairId]
0000000006003221 mov ecx,30h
0000000006003226 rep movs byte ptr [rdi],byte ptr [rsi]
0000000006003228 mov rax,qword ptr [piConstruct]
0000000006003230 mov rax,qword ptr [rax]
0000000006003233 lea r9,[rsp+230h]
000000000600323B mov r8d,800h
0000000006003241 mov edx,dword ptr [iHighNodeId]
0000000006003248 mov rcx,qword ptr [piConstruct]
0000000006003250 call qword ptr [rax+60h]
Y aquí está el desmontaje después de la llamada a la función:
0000000004B72470 mov qword ptr [rsp+20h],r9
0000000004B72475 mov dword ptr [rsp+18h],r8d
0000000004B7247A mov dword ptr [rsp+10h],edx
0000000004B7247E mov qword ptr [rsp+8],rcx
0000000004B72483 push rsi
0000000004B72484 push rdi
0000000004B72485 sub rsp,0A8h
0000000004B7248C mov rdi,rsp
0000000004B7248F mov rcx,2Ah
0000000004B72499 mov eax,0CCCCCCCCh
0000000004B7249E rep stos dword ptr [rdi]
0000000004B724A0 mov rcx,qword ptr [rsp+0C0h]
0000000004B724A8 mov qword ptr [rsp+90h],0FFFFFFFFFFFFFFFEh
Una vez que el sub rsp, 0A8h
todos los parámetros están configurados con datos, pero el parámetro sF tiene la dirección de la información correcta de structFoo en su campo de identificación, en lugar de usar esta dirección como su propio puntero. Cualquier orientación para resolver esto es muy apreciada.
Como nota al margen, lamentablemente no es una opción cambiar B::foo() para que tome la dirección de la estructura en lugar de la estructura en sí. Una gran parte del código heredado se basa en esta función que no tengo la autoridad para cambiar.
¡Gracias!
2 Respuestas
0
supongo, módulos A
y B
se compilan con diferentes convenciones de llamadas. Módulo A
pasa estructuras a funciones por referencia/puntero, mientras que módulo B
espera recibir estructuras en la pila, por valor.
Puede haber un modificador en B
archivo de encabezado de, así:
__weird_call void B::foo( int id, uint filter, structFoo sF );
Tal vez el compilador del módulo. A
no lo entiende, o algún otro archivo de encabezado lo define (#define __weird_call /* nothing */
), o algo por el estilo.
Respondido el 12 de junio de 12 a las 18:06
0
Me topé con esta página mientras buscaba una respuesta a un problema similar al que me enfrenté. Aunque no pude encontrar respuesta en internet, comparto la experiencia de depuración.
La siguiente estructura se pasó por referencia de una función a otra, y el receptor encontraría que los datos recibidos eran inesperados:
typedef struct
{
char time_st[30];
char pipe_no;
float loss;
float power[4];
int mode;
int count;
}Parameters;
Otro hallazgo fue que si defino la función de receptor en el mismo archivo que la función de llamador, el problema desaparecería.
Tras la depuración, se descubrió que la causa raíz era el uso espagueti de "#pragma pack" en archivos .h heredados en el sistema que causan problemas de empaquetamiento de estructuras, debido a la inclusión de varios archivos de encabezado heredados en el archivo .c de la función de llamada. , la estructura estaba empaquetada, pero en el archivo .c de la función receptora (que se escribió de nuevo durante la actividad del proyecto), la estructura se trató como desempaquetada.
Resolución: agregue suficiente relleno para alinear la palabra de estructura
typedef struct
{
char time_st[30];
char pad;
char pipe_no;
float loss;
float power[4];
int mode;
int count;
}Parameters;
Respondido 03 Jul 14, 06:07
No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas c++ visual-studio assembly x86 function-calls or haz tu propia pregunta.
¿Puedes mostrar el código para
B::foo( int id, uint filter, structFoo sF )
? - andrehay no hay necesidad para declarar estructuras como
typedef struct TAG_NAME {} REAL_NAME;
en C++. Solo hazstruct REAL_NAME {};
- John Dibling@ahenderson: esto suele ser un remanente de C. - John Dibling
¿Se compilan los dos módulos con argumentos de compilación idénticos? ¿Quizás cada uno de ellos se está compilando con una alineación diferente, por lo que el diseño físico de la estructura es diferente dentro de cada módulo? - cdhowie
Solo adivina: ¿tal vez tienes una violación de ODR (por ejemplo, debido a alguna macro que afecta la definición de la estructura)? - Igor R.