1

C# DllImport C++ dll を使用するときに 1 つの質問があります。Visual Studio 2010 を使用し、「アンマネージ コードのデバッグを有効にする」をオンにすると、実行時に常に「バッファー オーバーランが検出されました! ... バッファー オーバーランが発生しました」というメッセージが表示されます。プログラムの内部状態を破壊したことが検出されました。プログラムは安全に実行を継続できないため、すぐに終了する必要があります。」

この dll はサードパーティ ベンダーが提供するものであり、この dll を実行してもエラーはないとのことですが、どうすれば修正できますか?

私のM++ dll関数は、

int  avc_to_avi_convert(char* chPath_avc, char* chPath_avi, int pPrivate, PROGRESS_CALLBACK progress_callback);

void avc_to_avi_close(int* pFd_avi);

typedef void (*PROGRESS_CALLBACK)(int iPercent, int pPrivate);

そして、私はこのように私のC#dllimportでそれを使用しています:

public delegate void PROGRESS_CALLBACK(int _iPercent, int _pPrivate);

[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_convert", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]

public static extern unsafe int avc_to_avi_convert([MarshalAs(UnmanagedType.LPStr)] StringBuilder _inputAVC, [MarshalAs(UnmanagedType.LPStr)] StringBuilder _ouputAVI, int pPrivate, PROGRESS_CALLBACK _pg);

[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_close", CallingConvention = CallingConvention.Cdecl, CharSet = CharSet.Unicode)]

public static extern unsafe void avc_to_avi_close(int pFd_avi);

private void button1_Click(object sender, EventArgs e)
{
    int i = 0;
    StringBuilder inputFile = new StringBuilder(Application.StartupPath + @"\avc\abc.avc");//(@"C:\avc\abc.avc");
    StringBuilder outputFile = new StringBuilder(Application.StartupPath + @"\avi\abc.avi");//(@"C:\avi\abc.avi");

    if (avc_to_avi_convert(
        inputFile,
        outputFile,
        1,
        progress_func) > 0) { 

    }
}

public void progress_func(int iProgress, int pPrivate)
{
     if (iProgress == 100)
     {
         //success
     }
     else if (iProgress == -1)
     {
         //convert error
     }
     else if (iProgress == -2)
     {
         //Not enough disk space
     }
     else
     {
         //update progress
     }
}

コードを次のように変更しました。

[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_convert", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]

public static extern unsafe int avc_to_avi_convert([MarshalAs(UnmanagedType.BStr)] String _inputAVC, [MarshalAs(UnmanagedType.BStr)] String _ouputAVI, int pPrivate, PROGRESS_CALLBACK _pg);

[DllImportAttribute(@"..\xxx.dll", EntryPoint = "avc_to_avi_close", CallingConvention = CallingConvention.StdCall, CharSet = CharSet.Unicode)]

public static extern void avc_to_avi_close(ref int avi);

そしてそれを実行しましたが、それでも同じエラーが発生します。

4

2 に答える 2

2

1.) 呼び出し規約について確信がありますか? 試してみてくださいCallingConvention.StdCall。これを読む:

http://blogs.msdn.com/b/adam_nathan/archive/2003/05/21/56690.aspx

CharSet2.)属性に別の値を試して、パス引数のString代わりに使用してください。StringBuilderこれは良いリファレンスです:

http://msdn.microsoft.com/en-us/library/s9ts558h.aspx

3.) また、avc_to_avi_closeメソッドは次のようになります。

[DllImportAttribute("xxx.dll", EntryPoint="avc_to_avi_close")]
public static extern void avc_to_avi_close(ref int avi);

4.) 他に試し​​てみたいこと:

  • との異常な組み合わせを使用CharSetMarshalAsます。たとえば、上記のリンクからおよびとともにUnicode使用する必要があることがわかりますが、もちろん他の組み合わせを試すこともできます。LPWStrAnsiLPStr
  • extern メソッドをマークする必要はありませんunsafe

他のすべてのオプションを使い果たした場合は、C# コードに類似した C++ プログラムを作成してみませんか。

  • クラッシュした場合、エラーがライブラリにあることが証明されました。
  • クラッシュしない場合は、エラーが PInovke の使用にあることがわかり、私の回答から 12 個以上の組み合わせを 1 つずつ確認できます。
于 2012-10-07T05:49:55.063 に答える
0

デリゲートを p/invoke に渡し、ガベージ コレクターに解放させます。デリゲート オブジェクトがファイナライズされると、ネイティブ コードからの呼び出しを許可するように設定されたトランポリンの割り当てが解除されるため、これによりクラッシュが発生します。次に、ネイティブ コードがダングリング関数ポインターを呼び出します。

ガベージ コレクターは、ネイティブ コード内から使用されているオブジェクトをまったく認識しません。呼び出しの間、デリゲートへの参照を有効にしておく必要があります。デリゲート変数を追加してみて (一時変数を作成する暗黙の変換を使用しないでください) GCHandle、ネイティブ コードがそれを使用している限り、デリゲートを存続させるために使用します。

于 2012-10-08T04:35:50.273 に答える