LabVIEW のクラスタは VC++ のストラクチャとアラインメントが異なるのはなぜですか?



使用ソフトウェア: LabVIEW Development Systems>>Full Development System
使用ソフトウェア・バージョン: 5.0
使用ソフトウェア・バージョンに特化:
二次のソフトウェア: N/A

問題: LabVIEW のクラスタを DLL の構造体として変換しようとしているが、構造体の要素のアラインメントが数バイト異なっていて、時々クラッシュします。
LabVIEW 上で C のコードのアウトラインを作成したので正しいと思うのですが、アライメントが異なる理由は何でしょうか?


解決策:

Win-32 環境では、 LabVIEW はクラスタ内の要素を連続的に 1 バイトのパッキングサイズで保存します。
連続的に保存する事でクラスタ内にどのような要素が入っていても、空のバイトは作成されないようになっております。

英文で申し訳ございませんが、LabVIEW のメモリー保存に関しまして下記のリンクに詳細がございます。
How LabVIEW Stores Data in Memory
http://zone.ni.com/reference/en-XX/help/371361B-01/lvconcepts/how_labview_stores_data_in_memory/

しかしMicrosoft の Visual Studio のデフォルト設定は、データのナチュラルアライメントで8バイトのパッキングサイズを使用します。

--------------------------------
Microsoft MSDN からの抜粋

For types in memory, the default alignment is the same as its natural alignment
A base type such as short, float and __int64, and a pointer is aligned naturally if its representation starts at an address that is modulo its

size. All of the currently supported base types have sizes 1,2,4, or 8 bytes. Pointers have a size of 4 bytes in 32-bit environments and 8

bytes in 64-bit environments.
A compound type is aligned naturally if each of its components is aligned naturally relative to the beginning of the type and if there are no

unnecessary gaps (padding) between components.
--------------------------------

上記内容によりますと、VC++ のタイプのナチュラルアライメントは内蔵最大の要素と同様のサイズになります。

例えば VC++ の 構造体内に Int16 と Int32 のデータタイプが有りますと、Int16 の後に 2 バイトのパッディングが作成されます。
それは Int32 がナチュラルアラインメントを設定しているからです。
この際、コンパイラはデータをパッキングサイズかナチュラルアライメントの間で一番小さい方に合わせてパッキングします。
つきまして、ナチュラルアライメントより大きいパッキングサイズを指定しても実際作成されるパッキングサイズに影響は有りません。
VC++ でデフォルトのパッキングサイズ (8バイト) を指定すれば、ナチュラルアライメントになります。

LabVIEW と Visual C++ の間にデータをやり取りをする際に回避策として二通り考えられます。

1. DLL がもうすでにコンパイルされている状態でしたら、LabVIEW のクラスタにパディングとしてダミー変数を足し加える方法。
例えばクラスタ内に Int16 と Int 32 が有る際には、 Int16 の後にもう一つの Int16 足し加える事によって、 LabVIEW のメモリースペースが VC++ とラインアップし

ます。
[--------Int 16--------][----- Int 16 (dummy)---]
[-------------------Int 32-------------------]

2. VC++ 側でパッキングサイズを 1 バイトに変更する方法。
VC++ の 「typedef」 で、ストラクチャのパッキング順を指定するには 「pack pragma」 をご使用願います。

「pack pragma」 に関しましては下記のリンクをご参照願います。
Are There Examples of How the #pragma Pack Preprocessor Command Works?
http://digital.ni.com/public.nsf/websearch/5F94E0FD2BD4732786256547007D8EBB?OpenDocument

例えば:
------------------------------------------
#pragma pack(1) //次のストラクチャのパッキングサイズを 1 と設定
typedef struct {
int16 elt1;
int32 elt2;
} TD1;
.
.
.
#pragma pack() //パッキングサイズをコマンドラインのオプションで設定したのと同様
returns packing size to that specified in command line options
------------------------------------------
または:

#pragma pack(push)
#pragma pack(1)
typedef struct {
int16 elt1;
int32 elt2;
} TD1;
.
.
.
#pragma pack(pop)
------------------------------------------

Visual Studio はナチュラルアライメントを使用し、メモリーをより高速にアクセスできるようにしています。
LabVIEW はクロスプラットフォームが可能になるためナチュラルアライメントを使用しませんのでご了承ください。

Microsoft のメモリーアライメント、又はパッキング方式に関しましては下記のリンクをご参照願います。

Microsoft MSDN: C Language Reference: Storage and Alignment of Structures
http://msdn2.microsoft.com/en-us/library/1d48zaa8(vs.71).aspx

Microsoft MSDN: Storage and Alignment of Structures
http://msdn2.microsoft.com/en-us/library/aa243621.aspx



関連リンク:
Microsoft MSDN: C Language Reference: Storage and Alignment of Structures
http://msdn2.microsoft.com/en-us/library/1d48zaa8(vs.71).aspx

Microsoft MSDN: Storage and Alignment of Structures
http://msdn2.microsoft.com/en-us/library/aa243621.aspx

How LabVIEW Stores Data in Memory
http://zone.ni.com/reference/en-XX/help/371361B-01/lvconcepts/how_labview_stores_data_in_memory/

添付:





報告日時: 10/28/2001
最終更新日: 06/23/2009
ドキュメントID: 2EREKOG4