GlobalFreeを実行するとプログラムがクラッシュする場合があり、色々調べた結果、下記サンプルコードの様にGlobalFree相当の解放が勝手に行われているという結論に至りました。
文字列のマーシャリングをしているMallocEx1では「C++処理 MallocEx」というメッセージボックスが出ているときは、プロセスの仮想メモリ使用量(コミットサイズ)が500MiBを超え、「C#処理 MallocEx1呼び出し完了」というメッセージボックスが出るところまで行くと、GlobalFreeしていないのにメモリが勝手に解放されていることをタスクマネージャーなどで確認しました。
MallocEx2のようにマーシャリングをしない場合はメモリが解放されないため、メモリリークして仮想メモリ使用量(コミットサイズ)が増えて1000MiBを超えました。
GlobalAllocしたものが勝手に開放されることに大変驚いたのですが、このような挙動になることはCLRや.NET Frameworkの仕様で決められていることなのでしょうか。
C++DLL側
Visual Studio 2022
WindowsSDK 10.0.22000.0
C++
1#include<windows.h> 2char* tmp; 3void _stdcall MallocEx(int size,int value,char** ppRet) { 4 tmp = (char*)GlobalAlloc(GMEM_FIXED, size); 5 memset(tmp, value, size ); 6 MessageBox(NULL,"C++処理 MallocEx","",NULL); 7 if (size > 100) {//100文字で頭打ち 8 size = 100; 9 } 10 tmp[size-1] = 0; 11 *ppRet = tmp; 12} 13void _stdcall FreeEx() { 14 MessageBox(NULL, "C++処理 FreeEx", "", NULL); 15 GlobalFree(tmp); 16}
モジュール定義ファイル
C++
1LIBRARY 2EXPORTS 3 MallocEx 4 FreeEx
C++DLLを呼び出すC#側
Visual Studio 2022
.NET Framework4.8
C#
1using System; 2using System.Collections.Generic; 3using System.Linq; 4using System.Runtime.InteropServices; 5using System.Threading.Tasks; 6using System.Windows.Forms; 7using System.Text; 8using System.Text.RegularExpressions; 9 10namespace WindowsFormsApp1 { 11 internal static class Program { 12 13 [DllImport("TestDll.Dll",EntryPoint="MallocEx")] 14 extern public static void MallocEx1(int size,int value,ref string buff); 15 16 [DllImport("TestDll.Dll",EntryPoint="MallocEx")] 17 extern public static void MallocEx2(int size,int value,ref IntPtr buff); 18 19 [DllImport("TestDll.Dll")] 20 extern public static void FreeEx(); 21 22 [STAThread] 23 static void Main() { 24 int size = 1024*1024*500;//500MiB確保 25 string str1 = null; 26 IntPtr str2 = IntPtr.Zero; 27 28 MallocEx1(size,'0',ref str1); 29 MessageBox.Show("C#処理 MallocEx呼び出し完了 "+str1); 30 31 MallocEx1(size,'1',ref str1); 32 MessageBox.Show("C#処理 MallocEx呼び出し完了 "+str1); 33 34 MallocEx2(size,'0',ref str2); 35 MessageBox.Show("C#処理 MallocEx呼び出し完了 "+Marshal.PtrToStringAnsi(str2)); 36 37 MallocEx2(size,'1',ref str2); 38 MessageBox.Show("C#処理 MallocEx呼び出し完了 "+Marshal.PtrToStringAnsi(str2)); 39 40 } 41 } 42} 43 44
回答2件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2023/09/29 06:26