【发布时间】:2014-07-03 13:07:32
【问题描述】:
在将结构作为参数传递时,我无法追踪异常行为的原因。
所讨论的结构 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() 更改为获取结构的地址而不是结构本身不是一种选择。大量遗留代码依赖于我无权更改的此功能。
谢谢!
【问题讨论】:
-
你能显示
B::foo( int id, uint filter, structFoo sF )的代码吗? -
在 C++ 中不需要将结构声明为
typedef struct TAG_NAME {} REAL_NAME;。就做struct REAL_NAME {}; -
@ahenderson:这通常是 C 的保留。
-
这两个模块是否使用相同的编译器参数编译?也许它们每个都以不同的对齐方式编译,因此每个模块中结构的物理布局不同?
-
猜一猜:也许您遇到了 ODR 违规(例如,由于某些影响结构定义的宏)?
标签: c++ visual-studio assembly x86 function-calls