在将结构作为参数传递时,我无法追踪奇怪行为的原因。
有问题的结构structFoo具有以下声明:
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指向最近使用的字符串。函数调用后其他参数是正确的。
我不确定这种错位的原因,或者发生了什么,但在我看来,在函数调用完成之前,一切都在适当的位置。这是导致函数调用的反汇编:
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]
这是函数调用后的反汇编:
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信息的地址,而不是将此地址用作自己的指针。任何有关解决此问题的指导都非常感谢。
作为旁注,遗憾的是,更改B :: foo()以获取结构的地址而不是结构本身是一种选择。大量遗留代码依赖于我无权更改的此功能。
谢谢!
答案 0 :(得分:0)
我想,模块A
和B
是用不同的调用约定编译的。模块A
通过引用/指针将结构传递给函数,而模块B
期望按值接收堆栈上的结构。
B
的头文件中可能有一个修饰符,如下所示:
__weird_call void B::foo( int id, uint filter, structFoo sF );
也许模块A
的编译器不理解它,或者其他一些头文件定义它(#define __weird_call /* nothing */
),或者沿着这些行的东西。
答案 1 :(得分:0)
我偶然发现了这个页面,同时寻找我遇到的类似问题的答案。 虽然我在互联网上找不到答案,但分享调试经验。
以下结构通过引用从一个函数传递给另一个函数,接收者会发现收到的数据是意外的:
typedef struct
{
char time_st[30];
char pipe_no;
float loss;
float power[4];
int mode;
int count;
}Parameters;
另一个发现是,如果我在与调用函数相同的文件中定义接收函数,问题就会消失。
经过调试,发现根本原因是意大利面使用" #pragma pack"在系统中的遗留.h文件中导致结构打包问题 - 由于在调用函数的.c文件中包含了几个遗留头文件,结构被打包,但是在接收函数的.c文件中(在项目活动期间写的是新的,结构被视为解压缩。
分辨率:添加足够的填充以使结构字对齐
typedef struct
{
char time_st[30];
char pad;
char pipe_no;
float loss;
float power[4];
int mode;
int count;
}Parameters;