我在我一直在开发的这个 IDS/IPS 流量监控控制台应用程序中发现了内存泄漏。我以为是实体框架,原来是防火墙代码。以下代码在 .net 4.6.2 中运行良好,并且在 .net 核心中运行良好。但是,它有内存泄漏(特别是第二firewallRule
行):
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
INetFwRule firewallRule = firewallPolicy.Rules.OfType<INetFwRule>().Where(x => x.Name == fwRuleName).FirstOrDefault();
我必须每天重新启动应用程序,因为它会消耗尽可能多的内存。当它应该运行在 35MB 左右时,我已经看到它高达 12GB。也只需要一天左右的时间就可以达到如此高的水平。所以基本上每个电话都firewallRule
在吃〜5MB-10MB。似乎很疯狂,一条或一条空记录会占用那么多内存。
我相信是那一firewallRule
行,因为我已经在被调用的方法(以及与此相关的应用程序)中注释掉了所有其他行,当我最终注释掉该行时,泄漏就停止了。如果我的逻辑有缺陷,请告诉我。
如果要对其进行测试,则必须引用 以NetFwTypeLib
使该代码正常工作。
有谁知道为什么会发生这种情况以及如何解决?
更新:
以下是那些相信我没有全部评论的人的原始代码:
public static void FirewallSetup(string ip, string countryCode, bool isIpsString)
{
// FirewallControl fwCtrl = new FirewallControl();
// fwCtrl.Block(ip, countryCode, isIpsString);
//}
//private void Block(string ip, string countryCode, bool isIpsString)
//{
var remoteAddresses = "*";
string fwRuleName;
bool createNewFwRule = false;
//var fwRuleSuffix = SQLControl.GetFirewallRuleSuffix(countryCode).ToString();
//if (string.IsNullOrEmpty(fwRuleSuffix) || fwRuleSuffix == "0")
//{
fwRuleName = fwRuleNamePrefix + countryCode;
//}
//else
//{
// fwRuleName = fwRuleNamePrefix + countryCode + fwRuleSuffix;
//}
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
INetFwRule firewallRule = firewallPolicy.Rules.OfType<INetFwRule>().Where(x => x.Name == fwRuleName).FirstOrDefault();
//if (firewallRule == null)
//{
// createNewFwRule = true;
//}
//else
//{
// //We need the following for creating the remoteAddresses string below
// //but, also need to count as Windows has a 5000 ip limit per rule
// remoteAddresses = firewallRule.RemoteAddresses;
// string[] aRemoteAddresses = remoteAddresses.Split(",");
// int remoteAddressesCount = aRemoteAddresses.Length;
// //Log.Debug(">>>Firewall remote addresses scope=" + remoteAddresses);
// Log.Warning(">>>" + fwRuleName + " Firewall remote addresses count:" + remoteAddressesCount);
// //5000 would be 0 to 4999 I think?
// if (remoteAddressesCount >= 4999)
// {
// //If remote ip scope is 5000, create a new fw rule
// var newFwRuleNameSuffix = SQLControl.GetNewFirewallRuleSuffix(countryCode).ToString();
// fwRuleName = fwRuleNamePrefix + countryCode + newFwRuleNameSuffix;
// createNewFwRule = true;
// }
//}
//If necessary, we create a new rule
//TODO: Create another method for this?
//if (createNewFwRule)
//{
// firewallRule = (INetFwRule)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FWRule"));
// firewallRule.Name = fwRuleName;
// firewallPolicy.Rules.Add(firewallRule);
// firewallRule.Description = "Block inbound traffic from " + countryCode;
// firewallRule.Profiles = (int)NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_ALL;
// firewallRule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP;
// firewallRule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN;
// firewallRule.Action = NET_FW_ACTION_.NET_FW_ACTION_BLOCK;
// firewallRule.Enabled = true;
// //firewallRule.RemoteAddresses = ip;
// //firewallPolicy.Rules.Add(firewallRule); //throws error and not needed anyway
// //firewallRule.LocalPorts = "4000";
// //firewallRule.Grouping = "@firewallapi.dll,-23255";
// //firewallRule.Profiles = firewallPolicy.CurrentProfileTypes;
//}
//if (isIpsString || remoteAddresses == "*")
//{
// firewallRule.RemoteAddresses = ip;
//}
//else
//{
// firewallRule.RemoteAddresses = remoteAddresses + "," + ip;
//}
}
在生产中,它只是“按原样”执行此方法,只是吃掉内存。同样,它特定于 .Net Core,因为我在 .Net 4.6.1(未注释)中运行相同的代码一年多没有问题。
现在我想了想并把它注释掉了,我也可以把它通过一些循环并在内部进行故障排除。这是一场比赛...
它当前运行的服务器是 Windows Server 2016。
更新 2:它也可以在 Windows 10 中重现。这是重现错误的完整代码:
using System;
using System.Linq;
using NetFwTypeLib;
namespace FirewallLeakTesterCore
{
class Program
{
static void Main(string[] args)
{
int count = 0;
while (count < 1000)
{
Console.WriteLine(count += 1);
INetFwPolicy2 firewallPolicy = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2"));
INetFwRule firewallRule = firewallPolicy.Rules.OfType<INetFwRule>().Where(x => x.Name == "firewallRuleName").FirstOrDefault();
}
Console.ReadKey();
}
}
}
结果如下:
Visual Studio 诊断工具:
看起来像微软的错误?我想我会尝试解决这些内存分析器之一,但即使我发现了问题,我能做什么?这是对基本 Windows 库的基本调用,我认为这就是为什么评论中的某些人没有抓住重点。
我没有要求任何人记忆我的应用程序或追踪问题(从来没有......我已经这样做了)。我正在寻求替代解决方案。是否有可能完全可以使用的结构或 linq 问题或其他语句?
如果您想关闭这个问题,那就这样吧,但我很难相信没有其他人会遇到这个问题。