问题
I'm having trouble tracking down the cause of strange behavior in passing a structure as a parameter.
The structure in question, structFoo, has the following declaration:
typedef struct _structFoo {
int id;
BSTR szDescription;
VARIANT vData;
BOOL bTransient;
} structFoo;
I have two modules, A and B. Module A calls B::foo( int id, uint filter, structFoo sF ). In A, before the call, the structFoo structure is properly formed and filled with valid data. However, once the function call to B::foo() is made, the structFoo parameter has garbage data in it. Upon further examination, it turns out that the address of the copied struct is put into the id field, and the szDescription points to the most recently used string. The other parameters are correct after the function call.
I'm not sure the reason for this misalignment, or whatever is happening, but it appears to me that up until the function call is made, everything is in its proper place. Here's the disassembly leading up to the function call:
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]
And here is the disassembly after the function call:
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
After the sub rsp, 0A8h
the parameters are all set with data, but the sF parameter has the address of the correct structFoo information in its id field, rather than using this address as its own pointer. Any guidance on resolving this is greatly appreciated.
As a side note, changing B::foo() to take the address of the struct rather than the struct itself is unfortunately not an option. A great deal of legacy code relies on this function that I do not have the authority to change.
Thanks!
回答1:
I guess, modules A
and B
are compiled with different calling conventions. Module A
passes structures to functions by reference/pointer, while module B
expects to receive structures on the stack, by value.
There might be a modifier in B
's header file, like so:
__weird_call void B::foo( int id, uint filter, structFoo sF );
Maybe the compiler of module A
doesn't understand it, or some other header-file defines it out (#define __weird_call /* nothing */
), or something along these lines.
回答2:
I stumbled upon this page while looking for answer to a similar problem I faced. Although I could not find answer on the internet, sharing the experience of debugging.
The below structure was passed by reference from one function to other, and the receiver would find that the received data was unexpected:
typedef struct
{
char time_st[30];
char pipe_no;
float loss;
float power[4];
int mode;
int count;
}Parameters;
Another finding was that if I define the receiver function in the same file as caller function, the problem would disappear.
Upon debugging, the root cause was found to be spaghetti use of "#pragma pack" in legacy .h files in the system causing problems of structure packing -- due to inclusion of several legacy header files in the .c file of the caller function, the structure was packed, but in the .c file of the receiver function (which was written new during the project activity), the structure was treated as unpacked.
Resolution: add sufficient padding to make the structure word aligned
typedef struct
{
char time_st[30];
char pad;
char pipe_no;
float loss;
float power[4];
int mode;
int count;
}Parameters;
来源:https://stackoverflow.com/questions/11000798/structure-parameter-corrupted-on-function-call