1

C#のDotNet4アプリで使用しようとしているライブラリがあります。これはbinarayランタイムであるため、ライブラリソースにアクセスできません。エラーが発生します

PInvoke関数'XXXXXXXXXXX.WinAPI:: GetDCEx'を呼び出すと、スタックのバランスが崩れます。これは、マネージドPInvokeシグニチャがアンマネージドターゲットシグニチャと一致しないことが原因である可能性があります。PInvokeシグニチャの呼び出し規約とパラメータがターゲットのアンマネージドシグニチャと一致することを確認してください。

PInvokeStackImbalance MDAを無効にすると、デバッガーによってスローされなくなったため、アプリケーションが実行されます。これはアプリケーションが実行されないという問題を回避しますが、明らかに内部的な問題があります。

最近、NetFx40_PInvokeStackResilienceについて、app.configに配置できる要素について読みました。この要素は、マーシャリングレイヤーを使用して、誤ったプラットフォーム呼び出し宣言を検出および修正するようにランタイムに指示します(以前の.Netバージョンと同様)。

<configuration>
  <runtime>
    <NetFx40_PInvokeStackResilience enabled="1" />
  </runtime>
  .....
</configuration>

問題は、これがデバッガーに関して何もしていないように見えることです。それでもデバッガーはエラーを呼び出します。

私の質問は、PInvokeStackImbalance MDAを無効にする必要がありますか?

そして、NetFx40_PInvokeStackResilienceが機能し、マーシャリングレイヤーがその役割を果たしていることをどのように知ることができますか?

PS Visual Studio2010Expressを使用しています

PPS私はライブラリの所有者にDllImportsなどを修正する可能な解決策を書いて書いた。マーシャリングレイヤーは問題を回避するはずですが、パフォーマンスにコストがかかる可能性があります。さらに、その紛らわしく、理想的ではありません。ただし、それまでの間、ライブラリが更新されるまでは解決策が必要です。

4

1 に答える 1

1

不均衡なスタックは、厄介な種類の実行時の問題です。メソッドがスタックフレームを設定および破棄する方法により、スタックポインター値が正しくないという問題が隠される可能性があるため、デバッグビルドでそれを回避する傾向があります。スタックポインタはメソッドの終了時に復元されます。リリースビルドでは、そのような運が得られる可能性は低くなります。特にメソッドのインライン化により、スタックのセットアップ/ティアダウンコードが削除されます。

NetFx40_PInvokeStackResilience要素は、pinvokeマーシャラーを最適化したため、.NET4で必要でした。これは以前のリリースで機能していた悪いコードを壊す可能性があり、要素を追加するとその最適化が無効になります。プログラム全体にグローバルな影響を及ぼします。MDAを無効にすることを意図したものではなく、それは非常に現実的な問題を隠しているでしょう。ITスタッフに互換性の問題を回避する方法を提供するだけです。

pinvoke呼び出しを、呼び出しを行うだけの別のメソッドに入れることで、リスクを下げることができます。オプティマイザーがインライン化できないように、[MethodImpl(MethodImplOptions.NoInlining)]で装飾する必要があります。そのヘルパーメソッドは、out引数またはref引数を持つことはできず、構造体型の値を返すことはできません。また、呼び出し後に追加のコードを含めることはできません。

明らかに、この問題を実際に修正するために、できるだけ多くの時間を投資する必要があります。元のC宣言を手伝ってくれる人がいますが、私たちはあなたが彼を見つけるのを手伝うことはできません。pinvoke宣言を投稿しないと、誰かがそれを推測する可能性もなくなります。

于 2012-04-10T01:03:26.000 に答える