using & disposable - как поймать статическим анализом?
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 17.05.17 18:12
Оценка: +1 -1
Третий день гоняюсь за багом, связанным толи с утечкой ресурсов, толи памяти. Попутно наткнулся на одно место в клиентской части приложения, которое создаёт объект типа Stream и не освобождает его через Dispose:

using (new OperationContextScope((IClientChannel)service))
{
    Stream tempStream = service.GetChunkedImageStream(imageUID, compress, quality);
    {
        WriteStreamToFile(file, tempStream);
    }
}


tempStream надо бы тоже обернуть в using. Но что меня смутило — почему встроенный статический анализ ничего не сказал про это? В настройках проекта стоит анализ с набором правил "Microsoft Managed Recommended Rules" и никаких ворнингов на этой строке оно не показывает.
Умеет ли вообще встроенный анализатор ловить такое? Вроде не сложная вещь.
С уважением, Artem Korneev.
Re: using & disposable - как поймать статическим анализом?
От: VladCore  
Дата: 17.05.17 19:38
Оценка:
Здравствуйте, Artem Korneev, Вы писали:

AK>Третий день гоняюсь за багом, связанным толи с утечкой ресурсов, толи памяти.


Если используется HttpRuntime.Cache или MemoryCache, то не лечится. Они всю память жрут. А про наследника Stream я бы в последнюю очередь подумал — Любой класс может оставлять мусор в памяти на долго долго.
Re: using & disposable - как поймать статическим анализом?
От: Evgeny.Panasyuk Россия  
Дата: 17.05.17 20:25
Оценка: 5 (2)
Здравствуйте, Artem Korneev, Вы писали:

AK>Умеет ли вообще встроенный анализатор ловить такое? Вроде не сложная вещь.


Например анализатор не знает что происходит внутри WriteStreamToFile, который может быть вообще во внешней библиотеке. В частности WriteStreamToFile внутри может (технически) вызывать tempStream.Dispose().
В C++ по-умолчанию реализован именно тот вариант о котором ты говоришь — автоматический scope'инг, причём без необходимости писать явный using, а если же нужно убежать из scope — то используется явный move.
Re: using & disposable - как поймать статическим анализом?
От: Sharov Россия  
Дата: 18.05.17 08:31
Оценка:
Здравствуйте, Artem Korneev, Вы писали:

AK> толи с утечкой ресурсов, толи памяти.


Есть какая-то разница между этими утечками?

AK>Умеет ли вообще встроенный анализатор ловить такое? Вроде не сложная вещь.


Умеет. Попробуйте заинлайнить код метода WriteStreamToFile.
Кодом людям нужно помогать!
Re: using & disposable - как поймать статическим анализом?
От: Sinix  
Дата: 18.05.17 09:34
Оценка:
Здравствуйте, Artem Korneev, Вы писали:

AK>Третий день гоняюсь за багом, связанным толи с утечкой ресурсов, толи памяти.

mem profiler что показывает?
Re[2]: using & disposable - как поймать статическим анализом?
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 04.06.17 20:29
Оценка:
Здравствуйте, VladCore, Вы писали:

AK>>Третий день гоняюсь за багом, связанным толи с утечкой ресурсов, толи памяти.

VC>Если используется HttpRuntime.Cache или MemoryCache, то не лечится. Они всю память жрут. А про наследника Stream я бы в последнюю очередь подумал — Любой класс может оставлять мусор в памяти на долго долго.

Ни HttpRuntime.Cache, ни MemoryCache там не использовался. Помимо Stream, я нашёл там кучу других претендентов — неосвобождённые SqlCommand, DataTable и прочее. В чём именно была проблема — так и не ясно, но после обёртывания этих Displosable-объектов в using и полного переписывания одного медленного и частоиспользуемого метода, проблема перестала воспроизводиться.
Но мой вопрос был больше о том, почему статический анализ не тыкал нас носом в неосвобождённый Disposable.
С уважением, Artem Korneev.
Re[2]: using & disposable - как поймать статическим анализом?
От: Artem Korneev США https://www.linkedin.com/in/artemkorneev/
Дата: 04.06.17 20:31
Оценка:
Здравствуйте, Evgeny.Panasyuk, Вы писали:

AK>>Умеет ли вообще встроенный анализатор ловить такое? Вроде не сложная вещь.

EP>Например анализатор не знает что происходит внутри WriteStreamToFile, который может быть вообще во внешней библиотеке. В частности WriteStreamToFile внутри может (технически) вызывать tempStream.Dispose().

WriteStreamToFile в том случае это локальный метод того же класса, и никаких .Dispose() там не вызывается.
С уважением, Artem Korneev.
Re[3]: using & disposable - как поймать статическим анализом?
От: Evgeny.Panasyuk Россия  
Дата: 05.06.17 13:35
Оценка:
Здравствуйте, Artem Korneev, Вы писали:

AK>>>Умеет ли вообще встроенный анализатор ловить такое? Вроде не сложная вещь.

EP>>Например анализатор не знает что происходит внутри WriteStreamToFile, который может быть вообще во внешней библиотеке. В частности WriteStreamToFile внутри может (технически) вызывать tempStream.Dispose().
AK>WriteStreamToFile в том случае это локальный метод того же класса, и никаких .Dispose() там не вызывается.

Но анализатору нужно анализировать в том числе и этот метод, то есть поинт в том что локального анализа кода из первого сообщения недостаточно.
Это серьёзный барьер для анализаторов. Хотя, действительно, вполне преодолимый в некоторых частных случаях.
Re: using & disposable - как поймать статическим анализом?
От: ylp  
Дата: 06.06.17 21:01
Оценка:
Здравствуйте, Artem Korneev, Вы писали:

AK>Умеет ли вообще встроенный анализатор ловить такое? Вроде не сложная вещь.

FxCop is your friend
Re: using & disposable - как поймать статическим анализом?
От: Философ Ад http://vk.com/id10256428
Дата: 09.06.17 18:31
Оценка:
Здравствуйте, Artem Korneev, Вы писали:

AK>
AK>using (new OperationContextScope((IClientChannel)service))
AK>{
AK>    Stream tempStream = service.GetChunkedImageStream(imageUID, compress, quality);
AK>    {
AK>        WriteStreamToFile(file, tempStream);
AK>    }
AK>}
AK>


AK>tempStream надо бы тоже обернуть в using.


В общем случае — не нужно: service вполне может владеть этим стримом, и сам диспозить его. Собственно потому что "Get...()" — не тоже самое, что Create....().
В случае Create() — да, нужно обязательно диспозить, а в случай Get намного сложнее, например: GetInternalBuffer() — попробуй сказать, надо диспозить или нет.
Всё сказанное выше — личное мнение, если не указано обратное.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.