ab.com コミュニティ https://www.activebasic.com/forum/ |
|
アラインメント指定 https://www.activebasic.com/forum/viewtopic.php?t=891 |
ページ 1 / 1 |
作成者: | イグトランス [ 2006年4月01日(土) 00:37 ] |
記事の件名: | アラインメント指定 |
このコードでは16と出力されます。 コード: #strict #prompt Type Align(8) S1 x As DWord y As DWord End Type Print SizeOf (S1)しかしそれと同等と私が思った次のVC++のコードでは8が出力されます。 コード: #include <iostream> #include <windows.h> __declspec(align(8)) struct S1 { DWORD x; DWORD y; }; int main() { std::cout << sizeof (S1) << std::endl; }色々と試してみると,次のコードでは16と出力されました。 コード: #include <iostream> #include <windows.h> struct S1 { __declspec(align(8)) DWORD x; __declspec(align(8)) DWORD y; }; int main() { std::cout << sizeof (S1) << std::endl; }つまりアラインメントの対象が構造体全体であるか,個々のメンバであるかの違いのようです。 私はABのTypeに指定するAlignは構造体全体に対するアラインメントの指定であるべきだと思います。 つまり最初のABのコードは前者のVC++のコードに対応するようにするということです。 そもそもWinAPIで使われる構造体の中には8バイトアラインメントが指定されているものがあります。 そのような構造体をABに持ってくるとき,試しにType Align(8)としてみたことからこのことに気づきました。 VC++ではalign(8)と指定されているのに,ABでは付けるとエラーになるので省くということは, どうも違和感を感じさせます。それが前者の意味にしてほしいと言う理由ですね。 |
作成者: | NoWest [ 2006年4月01日(土) 13:24 ] |
記事の件名: | Re: アラインメント指定 |
この件につきましては、私のコラム執筆にあたり、山本様とメールで いくつかやりとりがありましたので、回答させて頂きます。 まず、ActiveBasicのアライメントについて抜粋 引用: VC++のアライメントの初期値は8byte、
VB、BC++のアライメントは4byteなんですが ABって何Byteなんでしょうか? 引用: アラインメントに初期値はありません。
簡単にいうと「ActiveBasicはそもそもアライメントと呼ばれる概念が希薄でこの説明は、非常に重要なポイントなので、よく理解してください。 そもそも、アラインメントとは、構造体の先頭を0としたときに、メンバ変数の データサイズでそのオフセットが割り切れない場合に、発生するものです。パ ディングを挿入して、そのメンバのデータサイズで割り切れるようにする働きが あるんですね。 APIで使用される構造体が問題なく動くように自動的に調節する。」ってことだそうです。 つまり、イグトランス様が試された コード: Type Align(8) S1 x As DWord y As DWord End TypeというコードはそもそもAlign(8)を付けなくてもActiveBasicでは問題なく 動くと言うことです。 結局Alignとは何なのか?ってことについて抜粋 引用: 構造体のアラインメントについては、コンパイラによって互換性が薄いようで
という返答を頂いております。す。CPUの処理速度に関係してくる内容なので、ターゲットマシンやOSによって 仕様が異なるという意味では納得はできますが、、、作っているこちらもややこ しい限りですf(^^ ・自動調節(デフォルト) ・互換性を重視するため、1バイトまたは2バイトでアラインメントをとる これら以外に関しては、必要なケースを見たことがありませんので、4~16バイ トアラインメントに関して、何か問題が生じるようであれば、VCのものと比較し ながらサポートを行おうと思います。 私も、最初は混乱しましたので、意見としてはイグトランス様に賛成です。 |
作成者: | イグトランス [ 2006年4月04日(火) 23:54 ] |
記事の件名: | |
最初にAlign(8)と付けてみたのはWin64への移植性が心配になったからです。 幸いにもx86系のCPUもアラインメントの扱いがなっていなくても動いてしまいますが,だからこそ心配になったのです。 そもそもNバイトにアラインメント(境界調整)するということは, メモリアドレスがNの倍数になる位置に配置するということのはずです。 それで気づいたのですが,これは0と出力されなくてはいけないはずなのですが,そうではありませんでした。 (私がコンパイルすると4が出力されました。) コード: #strict #prompt Type Align(8) S1 x As DWord y As DWord End Type Dim dw As DWord Dim s1 As S1 Dim address As ULONG_PTR Print (VarPtr(s1) As ULONG_PTR) Mod 8そしてこれと(メンバの配置以外は)ほぼ等価なはずのVC++のコードです。 コード: #include <iostream> #include <windows.h> __declspec(align(8)) struct S1 { DWORD x; DWORD y; }; int main() { using namespace std; DWORD dw; S1 s1; cout << reinterpret_cast<ULONG_PTR>(&s1) % 8 << endl; return 0; } |
作成者: | 山本 [ 2006年4月05日(水) 00:47 ] |
記事の件名: | |
アラインメント、一番頭が痛くなる問題ですね。アプリが強制終了して、原因を突き詰めたらデータの境界ラインが8の倍数になってなかったとか…。64ビットコンパイラの製作場面では、しょっちゅう遭遇していました。 では本題。 引用: 私はABのTypeに指定するAlignは構造体全体に対するアラインメントの指定であるべきだと思います。
指定したアラインメント値よりも小さなデータ型が存在するとき、現状のABの仕様ではムリヤリにアラインメントをとっているのが現状です。つまり最初のABのコードは前者のVC++のコードに対応するようにするということです。 そもそもWinAPIで使われる構造体の中には8バイトアラインメントが指定されているものがあります。 そのような構造体をABに持ってくるとき,試しにType Align(8)としてみたことからこのことに気づきました。 VC++ではalign(8)と指定されているのに,ABでは付けるとエラーになるので省くということは, どうも違和感を感じさせます。それが前者の意味にしてほしいと言う理由ですね。 私のほうでも、VC++での動作の違いを確認できました。移植のことを考えると、あわせたほうが無難ですね。アラインメント誤差によるバグは一番やっかいなものであるのはご承知のとおりですので、改善しようと思います。 引用: 最初にAlign(8)と付けてみたのはWin64への移植性が心配になったからです。
鋭いポイントをつかれますねf(^^幸いにもx86系のCPUもアラインメントの扱いがなっていなくても動いてしまいますが,だからこそ心配になったのです。 そもそもNバイトにアラインメント(境界調整)するということは, メモリアドレスがNの倍数になる位置に配置するということのはずです。 それで気づいたのですが,これは0と出力されなくてはいけないはずなのですが,そうではありませんでした。 (私がコンパイルすると4が出力されました。) 確かに、Win64では、8バイト区切りのデータ配置を機械語が要求してきます(違反すると、強制終了になります)。よって、Win64の環境下では、各変数の先頭アドレスは8で割り切れる数値となっています。これは、Win32の環境とは異なる点です。 このように、現状の64ビット版ActiveBasicでは8バイト境界ラインを意識した仕様になっておりますので、ご安心ください。 |
ページ 1 / 1 | 全ての表示時間は UTC+09:00 です |
Powered by phpBB® Forum Software © phpBB Limited https://www.phpbb.com/ |