0

在将结构作为参数传递时,我无法追踪奇怪行为的原因。

所讨论的结构 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() 以获取结构的地址而不是结构本身不是一种选择。大量遗留代码依赖于我无权更改的此功能。

谢谢!

4

2 回答 2

0

我在寻找我遇到的类似问题的答案时偶然发现了这个页面。虽然在网上找不到答案,分享下调试的经验。

下面的结构通过引用从一个函数传递到另一个函数,接收者会发现接收到的数据是意外的:

typedef struct
{
    char time_st[30];
    char pipe_no;
    float loss;
    float power[4];
    int   mode;
    int   count;
}Parameters;

另一个发现是,如果我在与调用函数相同的文件中定义接收函数,问题就会消失。

经过调试,发现根本原因是系统中遗留的.h文件中使用“#pragma pack”导致结构打包问题——由于在调用函数的.c文件中包含了几个遗留头文件,该结构被打包,但在接收函数的 .c 文件中(在项目活动期间编写的新文件)中,该结构被视为未打包。

解决方案:添加足够的填充以使结构字对齐

typedef struct
{
    char time_st[30];
    char pad;
    char pipe_no;
    float loss;
    float power[4];
    int   mode;
    int   count;
}Parameters;
于 2014-07-03T05:07:32.743 回答
0

我猜,模块AB是用不同的调用约定编译的。模块A通过引用/指针将结构传递给函数,而模块B期望通过值接收堆栈上的结构。

B的头文件中可能有一个修饰符,如下所示:

__weird_call void B::foo( int id, uint filter, structFoo sF );

也许模块的编译器A不理解它,或者其他一些头文件定义了它(#define __weird_call /* nothing */),或者类似的东西。

于 2012-06-12T17:40:01.033 回答