1. 程式人生 > >.NET CORE 2.0 zkweb.system.drawing Linux下記憶體BUG

.NET CORE 2.0 zkweb.system.drawing Linux下記憶體BUG

1.zkweb.system.drawing  linux下卡死

請先看這樣一段程式碼:

 

var image = new Bitmap(int_ImageWidth, letterHeight);
...
image = TwistImage(image, true, Next(1, 3), Next(4, 6));
MemoryStream ms = new MemoryStream();
image.Save(ms, ImageFormat.Jpeg);
image.Dispose();


//正弦扭曲
public Bitmap TwistImage(Bitmap srcBmp, bool bXDir, double dMultValue, double dPhase)
        {
            var PI = 6.283185307;
            var destBmp = new Bitmap(srcBmp.Width, srcBmp.Height);
            var graph = Graphics.FromImage(destBmp);
            graph.FillRectangle(new SolidBrush(Color.White), 0, 0, destBmp.Width, destBmp.Height);
            graph.Dispose();
            double dBaseAxisLen = bXDir ? destBmp.Height : destBmp.Width;
            for (var i = 0; i < destBmp.Width; i++)
            {
                for (var j = 0; j < destBmp.Height; j++)
                {
                    double dx = 0;
                    dx = bXDir ? PI * j / dBaseAxisLen : PI * i / dBaseAxisLen;
                    dx += dPhase;
                    var dy = Math.Sin(dx);
                    int nOldX = 0, nOldY = 0;
                    nOldX = bXDir ? i + (int)(dy * dMultValue) : i;
                    nOldY = bXDir ? j : j + (int)(dy * dMultValue);

                    var color = srcBmp.GetPixel(i, j);
                    if (nOldX >= 0 && nOldX < destBmp.Width
                        && nOldY >= 0 && nOldY < destBmp.Height)
                    {
                        destBmp.SetPixel(nOldX, nOldY, color);
                    }
                }
            }
            srcBmp.Dispose();
            return destBmp;
        }

在windows上跑這樣一段程式碼時沒有任何問題,當我釋出在linux上的時候,居然死掉了,是死掉,沒有任何異常,網頁一直在等待中,搞得我非常納悶,對於我這個有強迫症的人來說,直接無限測試,找到位置,多次測試尋找中偶然得到一份記憶體錯誤的資訊

這個BUG是出在image.save 是時候,應該是記憶體錯誤,導致不再向下執行,不止這個執行緒,整個dotnet 癱瘓,無法接收處理新的請求,但卻沒有多餘的CPU佔用。導致這個問題出現的是TwistImage 中的srcBmp.Dispose(); 把這個放在最後一起釋放可以暫時迴避掉這個BUG

這個問題應該是因為這個外掛使用了非託管記憶體,導致底層出現記憶體溢位或者訪問已經釋放掉的指標。至於為何windows沒有崩潰,很有可能是因為程式碼是根據環境進行呼叫的,包括呼叫的系統api都可能不同,所以僅導致了僅linux下出現記憶體問題