3

重複していないフィールドが重複していると報告されている構造体があります。

[FieldOffset(8)]
Int32 X;

[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
[FieldOffset(12)]
string Y;

[FieldOffset(28)]
int Z;

報告されたエラーは次のとおりです。

タイプ「XXX」を読み込めませんでした...オフセット12にオブジェクトフィールドが含まれていますが、オブジェクトフィールドが正しく配置されていないか、オブジェクトフィールドと重なっています。

これは、リリース構成(TRACE、DEBUGフラグ、および安全でないコードが有効で、最適化がオフになっている)でのみ発生します。推測すると、どうなりますか?

UPD:@svickに感謝します。x64ビルドがマーシャリングに必要なものではないことを確認しました。

4

3 に答える 3

5

まず、リリース構成はこれとは何の関係もありません。影響を受けるのはプラットフォームターゲットです。x64に設定するとこの例外が発生しますが、x86に設定すると正常に動作します。

この動作の理由は、管理対象メモリ内ののレイアウトを指定するために使用されますが(ドキュメントにこれが記載されていない場合でも)、管理対象メモリでは使用されないためだと思います。FieldOffsetstructMarshalAs

このため、管理対象メモリ内のオブジェクトにはオフセット12に参照が含まれています。また、すべての参照は.Netで整列する必要があるため(32ビットアプリケーションでは4バイト、64ビットでは8バイト)、例外が発生します。アプリケーションを64ビットとして実行する場合。

したがって、問題はフィールドが重複していることではなく、エラーメッセージの他の部分です。フィールドが正しく配置されていません。

簡単な回避策は、アプリケーションをx86としてコンパイルすることです。それが不可能な場合は、これを修正する方法がわかりません。

于 2012-05-05T11:33:13.420 に答える
5

@svickの正解に注釈を付けると、ここでの問題は、構造体宣言が、CLRがオブジェクトの割り当てをアトミックにするという確固たる約束に違反していることです。これは64ビットモードでは機能しません。オフセットが12の場合、オブジェクトポインタはキャッシュラインの終わりにまたがることがあります。このような位置がずれているメンバーにアクセスするには、常に2回の読み取りまたは書き込みが必要であり、アトミックになることはありません。これは実際にはCLRタイプのベリファイアのバグだと思いますが、それはこのこぶを乗り越えるのに役立ちません。

確かに、これは32ビットコードと相互運用するために行っており、デバッグビルドのプラットフォームターゲット設定を正しく変更しましたが、リリースビルドの場合は変更するのを忘れていました。構成ごとの設定です。簡単に修正できます。リリース構成の設定も変更するだけです。

これを64ビットモードで動作させる必要がある場合は、fixed char[16]代わりに宣言する必要があります。

于 2012-05-05T13:04:31.757 に答える
0

システムのデータフィールドのデフォルトの配置は8バイトだと思います。Yにはオフセット16を使用する必要があります。

于 2012-05-05T11:32:59.577 に答える