C#代码创建内存泄漏
本文关键字:泄漏 内存 创建 代码 | 更新日期: 2024-09-19 19:28:12
我想写一个简单的C#程序/控制台应用程序来创建一个缓慢且可控的内存泄漏。我希望这个程序慢慢消耗系统内存。我需要这个来做我正在测试的其他事情。
有人建议我使用:
Marshal.AllocHGlobal(numbytes)
附在计时器上。
以下是我尝试实现的代码:
class Program
{
static Timer timer = new Timer();
static void Main(string[] args)
{
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
start_timer();
Console.Read();
}
static void timer_Elapsed(object sender, ElapsedEventArgs e)
{
IntPtr hglobal = Marshal.AllocHGlobal(100);
Marshal.FreeHGlobal(hglobal);
Process proc = Process.GetCurrentProcess();
Console.WriteLine(proc.PrivateMemorySize64);
}
private static void start_timer()
{
timer.Start();
}
}
输出似乎表明内存仍在管理中,垃圾回收正在完成其工作。有人能帮我吗?我的目标是创建内存泄漏并耗尽系统资源。有人请建议我的代码有什么问题,或者一个替代的,更好的选择。
对于泄漏,您需要实际泄漏内存。现在,你没有泄露任何信息,因为你释放了它:
IntPtr hglobal = Marshal.AllocHGlobal(100);
// DO NOT DO THIS IF YOU WANT A LEAK: Marshal.FreeHGlobal(hglobal);
我需要为运行在Azure应用程序服务中的应用程序的故障模式测试用例创建一个受控内存泄漏。
这是MVC类中的一个分支。
using System;
using System.Collections.Generic;
using System.Threading;
using System.Web;
using System.Web.Mvc;
using log4net;
namespace foo.FooApp.MVC.UI.Controllers
{
[Route("memleak")]
public class MemLeakController : Controller
{
/*
* This code is a simple drop in solution that can be placed into a MVC controller application and will create a controlled memory leak.
* It provides three endpoints
* /InitMem - This is the initial page that provides a link to start the memory leak
* /RunMem - This page takes two parameters and will create a controlled memory leak.
* * Parameter 1: MemToAllocate, this is the amount of memory to consume per each itteration.
* * Parameter 2: MemToConsume, This is the number of allocation iterations.
* /ClearMem - This will reset (clear) any memory allocations.
* It was determined using a List of Bytes for memory allocation was a better solution than some of the other techniques, for example: Marshal.AllocHGlobal and static event EventHandler.
* For measuring memory allocation it was determined that using GC.GetTotalMemory rather proc.PrivateMemorySize64 provided more accurate results.
* This test will eventually cause an System.OutOfMemoryException. The Test can be reset by clicking on the clear memory link
* As of now App Services will fail with out of memory after about 3.4 GB of memory allocation.
*/
private static readonly ILog Logger =
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod()?.DeclaringType);
private const string MemClearHtml = "<ul><li><a href='"/memleak/ClearMem'")'">"
+ "<span>Reset Memory Leak Test</span>"
+ "</a></li></ul>";
private const string MemRunHtml = "<ul><li><a href='"/memleak/RunMem?MemToConsume=5&MemToAllocate=100'")'">"
+ "<span>Run Memory Leak Test</span>"
+ "</a></li></ul>";
private const string TextareaHeader = "<textarea id='"foo'" rows='"8'" cols='"50'">";
private const string TextareaFooter = "</textarea>";
private static long _memToAllocate = 1000000 * 100; // 100 MB
private static int _memToConsume = 5; // * _memToAllocate = 500 MB
private static long _lastMem;
// ReSharper disable once CollectionNeverQueried.Local
private static readonly List<byte[]> ListToConsume = new List<byte[]>();
/*
* Initial page to start the memory leak test
* Endpoint URI: /memleak
*/
[HttpGet]
public void Index()
{
Logger.Info("Init MEM " + GC.GetTotalMemory(false));
Response.Output.Write("Start Memory Leak Test {0} <br><br>", MemRunHtml);
Response.Output.Write("Current Memory Bytes: {0} <br>", GC.GetTotalMemory(false));
Response.Output.Write("Current Memory MB: {0} <br><br>",
GC.GetTotalMemory(false) / (1024 * 1024));
}
/*
* Main page for submitting memory allocation
* Endpoint URI: /memleak/RunMem?MemToConsume=5&MemToAllocate=100
*/
public void RunMem()
{
try
{
if (!string.IsNullOrEmpty(Request.QueryString.ToString()))
{
var nameValueCollection = HttpUtility.ParseQueryString(Request.QueryString.ToString());
_memToAllocate = long.Parse(nameValueCollection["MemToAllocate"]) * 1000000; // 1 MB
_memToConsume = int.Parse(nameValueCollection["MemToConsume"]);
}
Response.Output.Write("Memory Leak Test {0} <br><br>", MemClearHtml);
Response.Output.Write("Memory Leak Test {0} {1:HH:mm:ss} <br>", "Start:", DateTime.Now);
Response.Output.Write("Current Memory Bytes: {0} <br>", GC.GetTotalMemory(false));
Response.Output.Write("Current Memory MB: {0} <br><br>",
GC.GetTotalMemory(false) / (1024 * 1024));
Logger.Info("Start MEM " + GC.GetTotalMemory(false));
Response.Output.Write(TextareaHeader);
for (var i = 0; i < _memToConsume; i++)
{
ListToConsume.Add(new byte[_memToAllocate]);
Thread.Sleep(100);
var mem = GC.GetTotalMemory(false);
if (_lastMem == mem) continue;
Response.Output.Write("Current Memory Bytes: {0} 'n", mem);
Response.Output.Write("Current Memory MB: {0} 'n", mem / (1024 * 1024));
Logger.Info("Start MEM " + GC.GetTotalMemory(false));
_lastMem = mem;
}
Response.Output.Write(TextareaFooter);
Thread.Sleep(100);
Response.Output.Write("<br><br>Current Memory Bytes: {0} <br>", GC.GetTotalMemory(false));
Response.Output.Write("Current Memory MB: {0} <br>",
GC.GetTotalMemory(false) / (1024 * 1024));
Response.Output.Write("Memory Leak Test {0} {1:HH:mm:ss} <br><br><br>", "End:", DateTime.Now);
Response.Output.Write("Consume Next {0} {1} ",
_memToAllocate * _memToConsume / (1024 * 1024) + " MB",
MemRunHtml);
Logger.Info("Start MEM " + GC.GetTotalMemory(false));
}
catch (Exception ex)
{
Logger.Error(ex.Message);
LogError(ex);
}
}
/*
* Page to reset (clear) the memory allocation
* Endpoint URI: /memleak/ClearMem
*/
public void ClearMem()
{
Response.Output.Write("Start Memory Overload Test {0} <br><br>", MemRunHtml);
ListToConsume.Clear();
GC.GetTotalMemory(true);
Thread.Sleep(100);
Response.Output.Write("<br>Current Memory Bytes: {0} <br>", GC.GetTotalMemory(false));
Response.Output.Write("Current Memory MB: {0} <br>",
GC.GetTotalMemory(false) / (1024 * 1024));
Response.Output.Write("Memory Overload {0} {1:HH:mm:ss} <br>", "End:", DateTime.Now);
Logger.Info("Stop MEM " + GC.GetTotalMemory(false));
}
private void LogError(Exception ex)
{
LogManager.GetLogger(typeof(MvcApplication)).Error(ex);
}
}
}