[Fortify][.NET]Unreleased Resource: Streams 排除

明明同事用了using來確保區塊結束時會呼叫Dispose()作到自動釋放資源,但還是被源碼檢測工具fortify舉報。呼~~來解題。

 

如下,Developer都很乖有使用using定義物件範圍來讓using區塊結束時呼叫Dispose()作到自動釋放資源

using (FileStream fsInFile = new FileStream(@"C:\Test\file.txt", FileMode.Open, FileAccess.Read, FileShare.None))
{
    using (StreamReader srInFile = new StreamReader(fsInFile, System.Text.Encoding.Default))
    {
        string strInfData;
        while ((strInfData = srInFile.ReadLine()) != null)
        {
            throw new Exception("somebody else"); //故意直接跳出method
        }
    }
}

 

另外,微軟docs對於using陳述式的說明:

提供方便的語法,以確保正確使用 IDisposable 物件。

但被掃出Unreleased Resource: Streams

查了using在微軟docs的說明,有一行吸引了眼球,文件她說即使發生Exception,也可以確保會執行Dispose

The using statement ensures that Dispose is called even if an exception occurs within the using block. 

看來是fortify誤判了。

 


修正方法

老招,繼續神鬼交鋒,那我們在出事前加上一行Dispose()

using (FileStream fsInFile = new FileStream(@"C:\Test\file.txt", FileMode.Open, FileAccess.Read, FileShare.None))
{
    using (StreamReader srInFile = new StreamReader(fsInFile, System.Text.Encoding.Default))
    {
        string strInfData;
        while ((strInfData = srInFile.ReadLine()) != null)
        {
            fsInFile.Dispose();
            throw new Exception("somebody else");
        }
    }
}

 

重新掃描:

結案!

 


實驗解構函式發生Exception跳出using區塊時是否會執行

除了看微軟Docs文件,我們也科學的做實驗。

我們有一個球員class:Footballer,New一個馬競前鋒grizmann起來執行射門之後,我們故意進入Exception,看看解構函示是否會執行?

using System;

namespace ConsoleApp1
{
    internal class Program
    {
        private static void Main(string[] args)
        {
            Console.WriteLine("程式開始");
            Attack();
            Console.WriteLine("程式結束");
        }

        private static void Attack()
        {
            using (Footballer griezmann = new Footballer())
            {
                try
                {
                    griezmann.Shot();
                    throw new Exception("Error");
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    return;
                }
            }
        }
    }

    internal class Footballer : IDisposable
    {
        public Footballer()
        {
            Console.WriteLine("建構函式");
        }

        public void Shot()
        {
            Console.WriteLine("射門!!!");
        }

        public void Dispose()
        {
            Console.WriteLine("解構函式");
            GC.SuppressFinalize(this);
        }
    }
}

 

有執行解構!資源會被釋放~

 

Semi Finals

期待的4強,就少了西班牙。

 


參考

微軟docs using陳述式

https://docs.microsoft.com/zh-tw/dotnet/csharp/language-reference/keywords/using-statement