2009-10-01 9 views
7

C#コードからアンマネージC++コードを呼び出すと、メモリリークが発生するようです。
C++は、ifstream.readを使用してファイルからデータを読み取り、それをVectorに書き込みます。Windows 7のマネージコードからアンマネージコードを呼び出すとメモリリークが発生する

これはWindows 7にアップグレードした後に起こります。Vistaでは発生しませんが、VistaでコンパイルされたネイティブDLLのバージョンを使用しても何も変更されません。
同じC++コードを直接実行し、管理対象の介入なしでメモリリークは発生しません。
管理プロセスを実行してもvshostプロセス内で実行すると、メモリリークは発生しません。

 [DllImport(DllPath, CharSet = CharSet.Unicode)] 
    [return: MarshalAs(UnmanagedType.I1)] 
    public static extern bool MyMethod(
     int x, 
     string y, 
     string z, 
     bool v, 
     bool w); 

とネイティブ1::私はC++から呼び出す

MyDll_Export bool APIENTRY MyMethod(
int x, 
const wchar_t* y, 
const wchar_t* z, 
bool v, 
bool w) 

が、私はこのようにそれを呼び出す:

MyMethod(1, L"My String 1", L"My String 2", true, true) 

私をここ

は、コールサインですマネージド・メモリとアンマネージ・メモリのパフォーマンス・カウンタを見ると、すべてのメモリがアンマネージ・コードに由来することがわかります。
マーシャリングが非常に単純であることを考慮すると、なぜC++を直接呼び出すかC#を呼び出すかの違いが理解できません。
私はなぜこれがWindows 7(両方のWindowsインストールで.net 3.5 SP1を使用していた)でのみ起こるのかわかりません。

誰にでもこの理由が考えられますか?

また、誰かがWindows 7で動作するネイティブメモリプロファイリングツールを知っていれば、私は喜んでいるはずです(今のところ、すべての明示的なメモリ割り当てをコンソールに出力していて、違いはありません)。

+0

LeakDiag [http://mcfunley.com/277/using-leakdiag-to-debug-unmanaged-memory-leaks]またはAutomatedQAのAQTimeは、アンマネージドリーク解析を実行できます。 –

+0

メモリ消費量を測定するパフォーマンスカウンタはどれですか? –

+0

"vshost.exe"という質問にタグを付けました。メモリ消費量を測定すると、アプリケーションはVisual Studioで実行されますか? –

答えて

5

問題は、C#データ型をC++のカウンタ部分にマーシャリングすることに関連していると確信しています。戻り値boolを符号付きの1バイト値にマーシャリングしているので、多分関数の引数に同じことをする必要がありますか? C#のbool型は4バイトですが、おそらくそこに漏れていますか?

また、文字列にアンマネージタイプを指定すると役立ちます。

[DllImport(DllPath, CharSet = CharSet.Unicode)] 
[return: MarshalAs(UnmanagedType.I1)] 
public static extern bool MyMethod(
     int x, 
     [MarshalAs(UnmanagedType.LPWStr)] 
     [In] string y, 
     [MarshalAs(UnmanagedType.LPWStr)] 
     [In] string z, 
     [MarshalAs(UnmanagedType.I1)] 
     bool v, 
     [MarshalAs(UnmanagedType.I1)] 
     bool w); 

commentorの説明:一般に

For the C++ bool type:

、ゼロまたはヌルポインタ 値をfalseに変換され、他の 値がtrueに変換されます。

...

1998 C++標準ライブラリには、ブールのためのベクター テンプレートの 特殊化を定義します。 の説明は、 の実装では の要素をパックして、すべてのブールがメモリの1ビットだけを に使用するように指示しています。

だから、どのような値を使用しても、trueまたはfalseの値を持つC++のブール値が得られます。

+0

boolのサイズが一致しない場合、メモリリークは発生しませんが、おそらくアクセス違反、または何らかの種類のスタック破損が発生する可能性があります。 – user7116

+0

素晴らしいファイルscott、c#は4バイトとしてboolsをマーシャルします。 vとwにはmarshalas属性がありませんでした。 http://blogs.msdn.com/oldnewthing/archive/2009/08/13/9867383.aspx –

+0

err。 「見つける」という意味の –

2

残念なことに、文字列を使用すると、マーシャリングは簡単ではありません。

この問題を追跡するのに役立つデータがさらに必要になります。あなたは

  • がどのように文字列のメモリがネイティブコードで管理されている以下の

    • ネイティブメソッドシグネチャを提供することができますか?
    • APIを使用するC++サンプルですか?

    EDIT

    次のシグネチャを試してみてください。これは両方向にメモリをマーシャリング代わりのみにデータを渡すことではないCLRに指示します。

    [DllImport(DllPath, CharSet = CharSet.Unicode)] 
        [return: MarshalAs(UnmanagedType.I1)] 
        public static extern bool MyMethod(
          int x, 
          [In] string y, 
          [In] string z, 
          bool v, 
          bool w); 
    
  • +0

    ありがとう、更新された質問、渡された文字列は定数です。 –

    +0

    [In]は助けになりませんでしたが、VistaとWindows 7の間でどう変わるのですか? また、このメソッドを1回だけ呼び出すとは言及していませんでした。 –

    1

    私のメモリリークを見つけたとき、私はCLR Profilerの使用が役に立ったと評価してい。

    0

    メモリリークが発生していませんか?

    メモリリークを判断する基準は何ですか?あなたはパフォーマンスカウンターからそれを見ることができると言いますが、実際に何を観察していますか?あなたは漸進的に上昇する曲線、または高いレベルに落ち着く曲線を見ますか?高いメモリ消費量は、しばしばメモリリークのために混乱します。

    btw。 C++の関数定義も投稿できますか?

    +0

    私は連続的に上昇する曲線を見る。 体を意味するC++関数定義を投稿しました。ifstream.readを使用してファイルからデータを読み込みます。 –

    関連する問題