2017-10-26 24 views
1

CおよびC++では、構造体のパディングをコンパイラ固有のものとして扱うように教えられています。したがって、シリアライゼーションなどのためにそれに依存しません。構造体のパディングの信頼性

一方、サードパーティのダイナミックライブラリまたは共有オブジェクトにリンクするたびに、一貫した構造体パディングを使用します。

のは、<windows.h>からの例を見てみましょう:

typedef struct _SECURITY_ATTRIBUTES { 
    DWORD nLength; 
    LPVOID lpSecurityDescriptor; 
    BOOL bInheritHandle; 
} SECURITY_ATTRIBUTES, *PSECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES; 

HANDLE WINAPI CreateThread(
    _In_opt_ LPSECURITY_ATTRIBUTES lpThreadAttributes, 
    _In_  SIZE_T     dwStackSize, 
    _In_  LPTHREAD_START_ROUTINE lpStartAddress, 
    _In_opt_ LPVOID     lpParameter, 
    _In_  DWORD     dwCreationFlags, 
    _Out_opt_ LPDWORD    lpThreadId 
); 

KERNEL32そして、私たちは、Kernel32.dllのを作成するために使用されたコンパイラ気にはならないが、コンパイラ定義の構造体のパディングが異なるコンパイラを使用した場合のことを意味し.dllは、_SECURITY_ATTRIBUTESポインタを、アプリケーションのパック方法とは別に参照解除することがあります。

  • なぜ構造体のパディングに無関係で、サードパーティのDLLに構造体ポインタを渡すことができるのか説明できますか?
  • ダイナミックにロードされたDLL/SO(LoadLibraryまたはdlopenを使用して)に対して同じ根拠が働きますか?
  • #pragma packを使用すると、この懸念事項はすべて消えますか?
  • もしそうなら、#pragma packは構造シリアル化のための信頼できる解決策になるでしょうか?
+1

winapiヘッダーは、これが間違っていないことを保証するために大きな問題を抱えています。あなたのスニペットで部分的に見ることができますが、それは単なるvoid *ではなく、署名されていないがDWORDであるLPVOIDです。 Etceteraは、一般的なタイプのシステムを釘打ちすることが重要です。 winapiで使用される構造の多くは、構造のサイズ、余分な保険と設計の変更に対する弾力性を格納するフィールドを持っています。 SECURITY_ATTRIBUTESは、nLengthフィールドに注意してください。そして、#pragmaパックがたくさんあります。 –

+0

*一方、サードパーティ製のダイナミックライブラリや共有オブジェクトにリンクするときは、一貫した構造体パッディングを使用します* well-designedインタフェースは構造体のパディングの仕様に依存しません.... –

+0

@ AndrewHenleこれは、インターフェイスを設計するときに、ユーザーが初期化した構造体または構造体ポインタを渡すことを期待するのは悪いことですか?私はしばしば、ライブラリが構造体のためにメモリを割り当て、メソッドが呼び出されるたびにポインタがハンドルとして返されることを期待しています。 – Stewart

答えて

2

あなたはかなり正しいです。構造体の埋め込みとレイアウトは実装の詳細であり、コンパイラは自由に独自の選択を行うことができます。

しかし実際には、特定のプラットフォームで有用なコンパイラは、プラットフォームABIに準拠する必要があります。プラットフォームABIに準拠していないコンパイラを作成しようとすると、まったく役に立たないでしょう。

このため、使用するコンパイラがプラットフォームABIと互換性があると想定するのは安全です。実行できないコンパイラは見つかりません。

+0

したがって、直列化されたフォームが同じプラットフォームに残っている限り、実際には構造体を直列化できます。ソース/ターゲットプラットフォームABIがあなた自身のものと一致することを保証することはできないので、これは実行することを意味しますが、ネットワーク通信には依存することはできません。 (もちろん、ポインタで何もシリアル化することはできませんが、それは別の主題です)。 – Stewart

+0

さらに、プロセスアーキテクチャが変更されないことを条件とする。構造のレイアウトは、32ビットおよび64ビットプラットフォームで異なります。とにかく、あなたはネットワーク上やディスク上に構造をblitしたくありません。だから私の見解では、それについてはあまりポイントを推論することはありません。 –

+0

構造体をディスクにblitしたくないのはなぜですか? – Stewart

関連する問題