Обнаружите утечку памяти?

#c# #memory-leaks

#c# #утечки памяти

Вопрос:

проще говоря, мой sqlservr.exe происходит ли утечка памяти, когда когда-либо моя служба использует ее. Итак, вопрос в том, где и почему! : (

Я инициализирую свое соединение как нули. и есть предложение finally, чтобы убедиться, что они закрыты… (я также пробовал .dispose в datareader, но не помогает).

Я пытался определить проблему больше дня. Все, что я могу сказать, это то, что это где-то здесь.

 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 за то, что он не сказал мне, что он кэширует память, которая не используется при подключении, поэтому просто увеличивается и увеличивается (пока это не понадобится).

Комментарии:

1. Если ваш сервер действительно протекает, мы не найдем его в этом фрагменте клиентского кода.

2. Извините, что слишком ленив, чтобы дать правильный ответ, но блоки «Использование» — это лучший способ обработки IDisposables, чем то, что у вас там происходит, try / catch / finally.

3. В приведенном выше коде вы не удаляете свой SqlDataReader, и я не думаю, что ваше соединение также удаляется. Как указано в некоторых других ответах, вы должны использовать ключевое слово «using», чтобы объекты автоматически удалялись. Кроме того, как вы узнаете, что у вас утечка памяти? Как вы это определили?

4. используя диспетчер ресурсов, он просто растет и растет. Sqlserv — это база данных. Это мой код веб-сервиса, подключающийся к базе данных. Что-то не закрывается или что-то в этом роде, в результате чего память на sqlservr.exe идти вверх (и никогда не опускаться). Я попробую использовать, это звучит как идея получше.

5. @Doomsknight: какой объем памяти разрешено использовать SQL Server в его конфигурации? Перестает ли он увеличиваться при этом пределе? Вы сравниваете этот метод, делая то же from самое и where для каждого вызова?

Ответ №1:

Реорганизуйте свой код с помощью этого ключевого слова: используя

Занятие памяти не является детерминированным, в вашем примере эффективная память, используемая исполняемым файлом, будет освобождена только при сборке мусора, поэтому вы можете увидеть увеличение памяти, но это может быть не проблемой, рано или поздно она будет собрана, и память вернется к правильному значению.

После просмотра комментария проблема, похоже, не в вашем коде C # (также, если используется ключевое слово using, это хорошая идея!), Если есть проблема…

SQL Server будет увеличивать объем занимаемой памяти до тех пор, пока у него не появится доступная память, он предназначен для такой работы. В вашем примере каждый раз, когда вы передаете новое предложение where, оно будет кэшировать инструкцию SQL, и поэтому использование памяти будет увеличиваться до тех пор, пока у вас не появится доступная память.

В этом случае я предлагаю вам провести рефакторинг вашего кода, чтобы использовать хотя бы параметры SQL для создания предложения where, чтобы SQL всегда оставался неизменным, и изменялись только параметры, таким образом, SQL server будет кэшировать только один оператор SQL, а не тысячи. Еще лучше создать хранимую процедуру, но параметров обычно достаточно.

Имейте также в виду, что способ, которым вы создаете свой оператор SQL, действительно небезопасен и может привести к атакам с использованием SQL-инъекций, использование параметров также исправит это.

С уважением

Massimo

Комментарии:

1. используя диспетчер ресурсов, sqlservr.exe поднимается все выше и выше. У меня это было какое-то время, и ни разу оно не отключилось. Когда этот веб-сервис начинает вызываться 100 раз.. до 1000, без перезапуска сервера, тогда у него закончится память.

2. Строка «where» создается из переданных параметров, это всего лишь метод, который я использовал для повторного использования. предотвращение повторения кода. Я применил какое-то предотвращение sql-инъекций к своим строковым параметрам. Мы надеемся, что другой член моей команды проверит качество, чтобы убедиться, что я все сделал правильно. Спасибо, что указали на это.

Ответ №2:

ваш Conenction sqlConCount никогда не утилизируется.

реализация Dispose SqlConnection закрывает соединение перед удалением. поэтому лучше всего было бы использовать команду using для подключения, и вы можете быть уверены, что проблема не возникнет.

но поскольку вы не сохраняете ссылку, она в любом случае должна быть собрана из мусора, так что на самом деле это не проблема. вы на 100% уверены, что утечка памяти здесь?

Комментарии:

1. Почти уверен. Я вызываю этот метод (вообще не запуская никакого другого кода!), И мой sqlservr.exe поднимается все выше и выше, и выше, и выше, пока я не начинаю плакать: (.

Ответ №3:

Похоже, вы возвращаете свое целое число, прежде чем, наконец, у блока появится шанс сработать. Попробуйте назначить его в блоке try и вернуть его после блока finally

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

Комментарии:

1. finally будет вызываться любым способом, даже если вы завершаете метод возвращением

2. Да, он все равно выполняется. Я проверил, просто чтобы убедиться, что это не проблема 🙂

Ответ №4:

я думаю string string , что вызывает утечку, swtich в StringBuilder. кроме того, вы не SqlConCount удаляете и dataCount (вы могли бы попытаться реорганизовать свой код с помощью using

Комментарии:

1. «строка строка» не вызывает утечки памяти. В этом примере использование StringBuilder не дало бы никакого выигрыша.

2. всем известно, что конкатенация выделяет новый объект и копирует в него данные

3. Это правда. Это НЕ утечка памяти.