在Windows 10上,即使在调用Dispose方法之后,System.Drawing.FontFamily.IsStyleAvailable方法似乎也将分配的空间留在内存中。
我写了一个简单的控制台应用程序来测试它:
using System;
using System.Drawing;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static string getMemoryStatusString()
{
using (Process p = Process.GetCurrentProcess())
{
return "(p: " + p.PrivateMemorySize64 + ", v:" + p.VirtualMemorySize64 + ")";
}
}
static void Main(string[] args)
{
string s = getMemoryStatusString();
foreach(FontFamily fontFamily in FontFamily.Families)
{
Console.Write(fontFamily.Name + " " + getMemoryStatusString() + " -> ");
fontFamily.IsStyleAvailable(FontStyle.Regular);
fontFamily.Dispose();
Console.WriteLine(getMemoryStatusString());
}
string e = getMemoryStatusString();
Console.WriteLine(s + " -> " + e);
Console.ReadLine();
}
}
}
有关为何发生这种情况的任何想法?
提前致谢!
答案 0 :(得分:0)
如果内存泄漏会出现gdiplus.dll
,FontFamily.IsStyleAvailable()
实际上会对GdipIsStyleAvailable()
进行外部调用。
来自ILSpy:
public bool IsStyleAvailable(FontStyle style)
{
int num2;
int num = SafeNativeMethods.Gdip.GdipIsStyleAvailable(new HandleRef(this, this.NativeFamily), style, out num2);
if (num != 0)
{
throw SafeNativeMethods.Gdip.StatusException(num);
}
return num2 != 0;
}
反过来定义为:
[DllImport("gdiplus.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = true)]
internal static extern int GdipIsStyleAvailable(HandleRef family, FontStyle style, out int isStyleAvailable);
答案 1 :(得分:0)
我在工作站上看不到任何泄漏(但我使用 Windows 7 .Net 4.5 )。 测试程序存在一些问题
<div class="wrapper">
<div class="ideas__gallery">
<h3 class="ideas__gallery__h3">Headline</h3>
<div class="one"></div>
<div class="two"></div>
<div class="three"></div>
<div class="four"></div>
<div class="five"></div>
<div class="six"></div>
<div class="seven"></div>
</div>
</div>
我在等于之前看到内存之后的内存:
static string getMemoryStatusString() {
// Do not forget to collect the garbage (all the generations)
GC.Collect(2);
GC.WaitForFullGCComplete();
using (Process p = Process.GetCurrentProcess()) {
return "(p: " + p.PrivateMemorySize64 + ", v:" + p.VirtualMemorySize64 + ")";
}
}
// Suspected method
static void methodUnderTest() {
foreach (FontFamily fontFamily in FontFamily.Families) {
//Console.Write(fontFamily.Name + " " + getMemoryStatusString() + " -> ");
fontFamily.IsStyleAvailable(FontStyle.Regular);
//TODO: You must not do this: disposing instanse you don't own
fontFamily.Dispose();
}
}
// Test itself
static void Main(string[] args) {
// Warming up: let all the libraries (dll) be loaded,
// caches fed, prefetch (if any) done etc.
for (int i = 0; i < 10; ++i)
methodUnderTest();
// Now, let's run the test: just one execution more
// if you have a leak, s1 and s2 will be different
// since each run leads to leak of number of bytes
string s1 = getMemoryStatusString();
methodUnderTest();
string s2 = getMemoryStatusString();
Console.Write(s1 + " -> " + s2);
}
答案 2 :(得分:0)
调用dispose不会立即释放管理内存。它必须等到GC.Collect发生。如果要在Disposing之后测量内存,则应强制执行GC.Collect并等待最终确定。
执行强制垃圾收集,如下所示,在处理内存读取后再查看。
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();