循环中的 C# 内存泄漏

本文关键字:内存 泄漏 循环 | 更新日期: 2023-09-27 18:28:46

public void DoPing(object state)
{
    string host = state as string;
    m_lastPingResult = false;
    while (!m_pingThreadShouldStop.WaitOne(250))
    {
        Ping p = new Ping();
        try
        {
            PingReply reply = p.Send(host, 3000);
            if (reply.Status == IPStatus.Success)
            {
                m_lastPingResult = true;
            }
            else
            {
                m_lastPingResult = false;
            }
        }
        catch
        {
        }
        numping = numping + 1;
    }
}

知道为什么这段代码给我内存泄漏吗?我可以看到这是这段代码,因为将等待值更改为更小或更大的值会增加内存使用率。有人知道如何解决它吗?或者如何查看代码的哪一部分导致了它?

循环中的 C# 内存泄漏

在某些垃圾回收语言中,存在一个限制,即如果创建对象的方法仍未退出,则不会收集对象。

我相信.net在调试模式下以这种方式工作。引用本文;请注意粗体语句。

http://www.simple-talk.com/dotnet/.net-framework/understanding-garbage-collection-in-.net/

考虑当前正在运行的方法中的局部变量 成为 GC 根。这些变量引用的对象始终可以 通过声明它们的方法立即访问,因此 他们必须留在身边。这些根的寿命可以取决于 程序的构建方式。在调试版本中,局部变量持续存在 只要该方法在堆栈上。在发布版本中,JIT 能够查看程序结构以解决最后一点 在执行中,方法可以使用变量,并且 当不再需要它时,将丢弃它。此策略不是 始终使用并且可以关闭,例如,通过运行程序 在调试器中。

垃圾回收仅在内存压力大时才发生,因此仅看到内存使用量增加并不意味着存在内存泄漏,在此代码中,我看不出如何存在合法泄漏。您可以添加

GC.Collect();
GC.WaitForPendingFinalizers();

仔细检查,但不应该将其留在生产中。

编辑:有人在评论中指出Ping是一次性的。 不调用 dispose 可能会导致泄漏,最终会清理,但可能需要很长时间并导致与内存无关的问题。

try-catch中添加一个finally语句,如下所示:

catch() {}
finally
{
     Ping.Dispose();
}
using(var p = new Ping())
{
    try
    {
        var reply = p.Send(host, 3000);
        if (reply.Status == IPStatus.Success)
           _lastPingResult = true;
        else  
           _lastPingResult = false; 
    }
    catch(Exception e)
    {
       //...
    }
}

这可以从静态类中使用:

public static bool testNet(string pHost, int pTimeout)
{
    Ping p = new Ping();
    bool isNetOkay = false;
    int netTries = 0;
    do
    {
        PingReply reply = p.Send(pHost, pTimeout);
        if (reply.Status == IPStatus.Success)
        {
            isNetOkay = true;
            break;
        }
        netTries++;
    } while (netTries < 4);
    //Void memory leak
    p.Dispose();
    return isNetOkay;
}