发现内存泄漏



简单地说,我的sqlservr.exe是内存泄漏每当我的服务使用它。所以问题是,在哪里,为什么!(

我将连接初始化为null。并且有一个最后条款来确保它们是关闭的……(我也试过在数据读取器上。dispose,但没有帮助)。

我花了一天多的时间试图找出问题所在。我只能说它就在这里的某个地方。

private Int32 GetCount(String From, String Where)
{
    //Build SQL string from given parameters.
    String sql = "SET dateformat DMY SELECT COUNT(*) as Count FROM " + From + " WHERE " + Where;
    SqlDataReader dataCount = null;
    SqlCommand sqlCommCount = null;
    SqlConnection sqlConCount = null;
    try
    {
        sqlCommCount = new SqlCommand();
        sqlConCount = new SqlConnection();
        sqlCommCount.Connection = sqlConCount;
        sqlConCount.ConnectionString = "connectionstring";
        sqlCommCount.CommandText = sql;
        sqlConCount.Open();
        dataCount = sqlCommCount.ExecuteReader();
        while (dataCount.Read())
        {
            return Convert.ToInt32(dataCount["Count"]);
        }
        return 0;
    }
    finally
    {
        sqlConCount.Close();
        sqlCommCount.Dispose();
        if (dataCount != null)
            dataCount.Close();
    }
}

解决:

  1. 无泄漏

  2. 我讨厌Sqlserver不告诉我它缓存内存,而不是在使用连接时,所以只是增加和增加(直到需要)。

使用

用关键字重构你的代码

内存占用是不确定的,在你的样本中,可执行文件使用的有效内存只有在垃圾收集发生时才会被释放,所以你可以看到内存增加,但这可能不是问题,它迟早会被收集,内存将返回到一个适当的值。

看到注释后,问题似乎不在你的c#代码中(如果使用using关键字,这也是一个好主意!),如果有问题…

SQL Server将增加内存占用,直到它有可用的内存,它被设计成这样工作。在您的示例中,每次传递一个新的where子句时,它都会缓存SQL语句,因此内存使用将增加,直到您有可用的内存。

在这种情况下,我建议你重构你的代码,至少使用SQL参数来创建where子句,这样SQL将始终保持不变,只有参数改变,这样SQL服务器将只缓存一条SQL语句,而不是数千条。更好的方法是创建一个存储过程,但通常有参数就足够了。

请记住,你构建SQL语句的方式是非常不安全的,可能会导致SQL注入攻击,使用参数也会解决这个问题。

马西莫

您的约定sqlConCount从未真正被处理过。

SqlConnection的Dispose实现在Dispose之前关闭连接。所以最好是使用using命令来连接,这样你就可以确保问题不会出现在那里。

但是当你不保存引用时,它应该被垃圾收集,所以不是真正的问题。你百分之百确定内存泄漏在这里吗?

看起来你在最后一个块有机会触发之前返回你的整数。尝试在Try块中分配它,并在finally块

后返回它
int value = o;
try
{
  ... 
  value = Convert.ToInt32(dataCount["Count"]);
}
finally
{
//close connection
}
return value;

我认为string + string导致泄漏,切换到StringBuilder。你也不处置SqlConCountdataCount(你可以尝试重构你的代码使用using

最新更新