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
は構造シリアル化のための信頼できる解決策になるでしょうか?
winapiヘッダーは、これが間違っていないことを保証するために大きな問題を抱えています。あなたのスニペットで部分的に見ることができますが、それは単なるvoid *ではなく、署名されていないがDWORDであるLPVOIDです。 Etceteraは、一般的なタイプのシステムを釘打ちすることが重要です。 winapiで使用される構造の多くは、構造のサイズ、余分な保険と設計の変更に対する弾力性を格納するフィールドを持っています。 SECURITY_ATTRIBUTESは、nLengthフィールドに注意してください。そして、#pragmaパックがたくさんあります。 –
*一方、サードパーティ製のダイナミックライブラリや共有オブジェクトにリンクするときは、一貫した構造体パッディングを使用します* well-designedインタフェースは構造体のパディングの仕様に依存しません.... –
@ AndrewHenleこれは、インターフェイスを設計するときに、ユーザーが初期化した構造体または構造体ポインタを渡すことを期待するのは悪いことですか?私はしばしば、ライブラリが構造体のためにメモリを割り当て、メソッドが呼び出されるたびにポインタがハンドルとして返されることを期待しています。 – Stewart