0

構造体をパラメーターとして渡す際の奇妙な動作の原因を追跡するのに苦労しています。

問題の構造体 structFoo には、次の宣言があります。

typedef struct _structFoo {
    int id;
    BSTR szDescription;
    VARIANT vData;
    BOOL bTransient;
} structFoo;

A と B の 2 つのモジュールがあります。モジュール A は B::foo( int id, uint filter, structFoo sF ) を呼び出します。A では、呼び出しの前に、structFoo 構造が適切に形成され、有効なデータで埋められます。ただし、B::foo() への関数呼び出しが行われると、structFoo パラメーターにガベージ データが含まれます。さらに調べてみると、コピーされた構造体のアドレスが 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

AモジュールとBは異なる呼び出し規約でコンパイルされていると思います。モジュール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 に答える