函数调用时结构参数损坏 [英] Structure parameter corrupted on function call
问题描述
我无法在传递结构作为参数时跟踪异常行为的原因。
I'm having trouble tracking down the cause of strange behavior in passing a structure as a parameter.
有问题的结构structFoo具有以下声明:
The structure in question, structFoo, has the following declaration:
typedef struct _structFoo {
int id;
BSTR szDescription;
VARIANT vData;
BOOL bTransient;
} structFoo;
我有两个模块A和B.模块A调用B :: foo(int id,uint filter,structFoo sF)。在A中,在调用之前,structFoo结构被正确地形成并用有效数据填充。但是,一旦对B :: foo()的函数调用,structFoo参数中就有垃圾数据。经进一步检查,结果是复制的struct的地址被放入id字段,并且szDescription指向最近使用的字符串。其他参数在函数调用后是正确的。
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
在 sub rsp,0A8h
之后,参数都设置了数据,但是sF参数在其id中有正确的structFoo信息的地址字段,而不是使用此地址作为自己的指针。非常感谢任何解决这个问题的指导。
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.
另一方面,改变B :: foo()来取结构的地址而不是结构本身是不幸的不是一个选项。
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.
谢谢!
推荐答案
我在寻找我面对的类似问题的答案时偶然发现了这个页面。
虽然我在互联网上找不到答案,但是分享了调试的经验。
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.
调试时,发现根本原因是在系统中遗留的.h文件中使用#pragma pack,导致结构打包问题 - 由于在调用函数的.c文件中包含了几个传统头文件,因此结构被打包,但是在接收函数的.c文件(在项目活动期间被写为新的)中,结构被当作解包。
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;
这篇关于函数调用时结构参数损坏的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!