2016-04-05 14 views
1

私は、Windowsでは、mallocはAllocHGlobalとは異なるCoTaskMemAllocとは異なります。 C#の消費者にとって、これは、mallocされたポインタを返すC関数を持っていれば、それを自由に呼び出す必要があることを意味します。 I P/Invokeで文字列戻り値の型を指定すると、CLRはCoTaskMemFreeを呼び出すはずであり、mallocされたポインタで失敗するはずです。CoTaskMemAlloc vmalloc v AllocHGlobal

しかし、私は実際にはこれを見ることができません。私はちょうどmalloc'd char *とP /文字列として呼び出す返すDLLを作成しました。メモリリークはありません。確かに、私が何を試みても、私は物事が失敗することはできません。私はmalloc、GlobalHAlloc、CoTaskMemAllocを呼び出し、無料の実装を使用しています。メモリリークはありません。同じメモリ空間が再利用されます。

これを強制的に失敗させるにはどうすればよいですか?あるいは、これは "実装定義"になっているはずのものですが、実際にはどちらか一方の方法で動作しますか?

これはVS2015 Update 2、Windows 8.1上にあります。

+0

エラーが発生した場合、コードは必ず失敗するとは限りません。時にはそうなるでしょうが、時にはそうではありません。あなたがmallocで割り当てて、CoTaskMemFreeで割り当てを解除すると、リークします。私はあなたの漏れの検出が間違っていると思います。 –

+0

私はCoTaskAllocMem/free、AllocHGlobal/freeをこの順番で試しました。同じポインタを返します。だからそれは確かに漏れていない。また、malloc(一度に1MB)を使って20GBを割り当てようとした後、P/InvokeのデフォルトとFreeHGlobal/CoTaskFreeMemで解放しました。リークなし(メモリ使用量の増加なし)。私が自由な機能を呼び出さなければ、プロセスはすぐに風船になる。 – MichaelGG

+1

非常に大きなメモリブロックを割り当てていますか?おそらくすべてのアロケータがそれを 'VirtualAlloc'への直接呼び出しに委譲します。一握りのバイトを割り当ててみてください。 –

答えて

5

これは確かに動作しませんでした。しかし、物事は変化しています。 Cランタイムライブラリwas changed in VS2012、それはもはや独自のヒープをもう作成しません。 VS2015の場合、このCのコード:\プログラムファイル(x86の)\ Windowsのキット\ 10 \ソース\ 10.0.10240.0 \ ucrt \ヒープの\ heap_handle.cppは関連しています。

// Initializes the heap. This function must be called during CRT startup, and 
// must be called before any user code that might use the heap is executed. 
extern "C" bool __cdecl __acrt_initialize_heap() 
{ 
    __acrt_heap = GetProcessHeap(); 
    if (__acrt_heap == nullptr) 
     return false; 

    return true; 
} 

注意GetProcessHeap(への呼び出し) Marshal.AllocHGlobal()が割り当て元と同じヒープを返します。だから、Marshal.FreeHGlobal()で割り当てを解除したときに、デバッグヒープからの例外やリークが発生することはありません。

CoTaskMemAlloc()の場合とほとんど同じです。関数にシングルステップ、私は以下を参照してください。

7638D1E1 mov   esi,dword ptr [g_CMalloc (76485EE0h)] 
7638D1E7 push  dword ptr [ebp+8] 
7638D1EA mov   esi,dword ptr [esi+0Ch] 
7638D1ED cmp   esi,offset CRetailMalloc_Alloc (763732C0h) 
7638D1F3 jne   CoTaskMemAlloc+44h (7638D214h) 
7638D1F5 push  0 
7638D1F7 push  dword ptr [g_hHeap (76485E68h)] 
7638D1FD call  dword ptr [[email protected] (76488228h)] 

g_hHeap変数の使用を注意してください。 GetProcessHeap()が返す値と同じ値を持つことがわかります。再び、と解放すると、割り当て解除関数のいずれもはうまく動作します。

これは私がWindows 10から入手したことに注意してください。古いバージョンのWindowsは同じように動作しません。そして、CRetailMalloc_Allocは、予期せぬ使い方をするあまり楽しくないランダマイザです。

これは確かに役立つものであり、プログラムが失敗する可能性はあまりありませんが、アプリをテストするときは実際には役に立ちません。嫌な、本当に、それは "私のマシン上でのみ動作する"障害モードを呼び出す。 Bah。

+0

それは素晴らしい情報です。どこかの人がこれについて言及してくれればうれしいです。質問や投稿のほんの一握りがうまくいきません。とにかく、これは私の実際の問題ではないと思うし、残念なことに私が心配しているすべてのプラットフォームで「機能する」。乾杯! – MichaelGG

+0

ドキュメントには、変更の対象となる実装の詳細が記載されているのはなぜですか? –

+0

正式な文書がクラッシュするとはっきりとは分かりませんが、件名に関するいくつかのより権威のある投稿があります。何年もの間、これがそうでなかったことを知っていると、他のプラットフォームで動作してはいけない理由を理解するのに役立ち、アプリの問題の原因としてこれをもっと早く排除するのに役立ちます。 – MichaelGG

関連する問題