函数调用时结构参数损坏 [英] Structure parameter corrupted on function call

查看:235
本文介绍了函数调用时结构参数损坏的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法在传递结构作为参数时跟踪异常行为的原因。

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆