2012-05-05 10 views
3

を構築するリリースに失敗しました。マーシャリングLayoutKind.Explicit構造体は、私が重なっとして<em>、非重複</em>フィールドが報告した構造体を持っている

[FieldOffset(8)] 
Int32 X; 

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

[FieldOffset(28)] 
int Z; 

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

は型「XXX」をロードできませんでした...それは、オブジェクトフィールドがで間違って整列または非オブジェクトのフィールドで重複している12のオフセットが含まれています。

リリース設定(TRACE、DEBUGフラグ、安全でないコードが有効、最適化がオフ)でのみ発生します。

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

+0

StructLayout属性で文字セットを指定していますか? http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.structlayoutattribute.charset.aspxのように?そうでない場合は、構造体が1バイト文字ではあるがワイド文字では正しくないので、ビルド間の文字セットの変な切り替えがあると思われます。 – tyranid

+0

'LayoutKind.Explicit'の代わりに' LayoutKind.Sequential'を使用できますか? 'FieldOffset '属性?それは常に可能ではありませんが、この場合は可能ですが、問題全体を回避することができます。 – hvd

答えて

4

最初に、リリース構成はこれとは関係ありません。それに影響を及ぼすのはプラットフォームターゲットです:x64に設定した場合、この例外が発生しますが、x86に設定するとうまく動作します。

私は、この動作の理由はFieldOffsetが管理するメモリ(ドキュメントはこのことを言っていない場合でも)にstructのレイアウトを指定するために使用されていることであるを考えるが、MarshalAsが管理するメモリで使用されていません。

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

だから、問題はそれがエラーメッセージの他の部分です、あなたはフィールドを重複しているということではない:フィールドが正しく整列しています。

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

0

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

5

注釈する@ svickの正しい答え、ここでの問題は、あなたの構造体の宣言は、CLRオブジェクトの割り当てがアトミックであることを作るハード約束に違反していることです。これは、オブジェクトポインタがキャッシュラインの終わりをまたぐことができるように、オフセットが12である64ビットモードでは機能しません。このような整列していないメンバーにアクセスするには、常に2回の読み取りまたは書き込みが必要であり、絶対にアトミックにすることはできません。私は実際にはCLR型の検証ツールのバグだと思っていますが、それはあなたがこのこん棒を過ぎるのを助けるつもりはありません。

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

あなたが本当にこれは64ビットモードで作業する必要があるなら、あなたは代わりにfixed char[16]としてそれを宣言する必要があります。

関連する問題