[SkiaSharp] AccessViolationException ์ฒ˜๋ฆฌ

Azure Function Service Bus Queue Trigger ํ™˜๊ฒฝ์—์„œ SkiaSharp์„ ์ด์šฉ ์ค‘์— AccessViolationException์ด ๋ฐœ์ƒํ–ˆ์—ˆ์Šต๋‹ˆ๋‹ค.

๊ด€๋ จํ•˜์—ฌ Github์— ์˜ฌ๋ ธ๋˜ ์งˆ๋ฌธ๊ณผ @evan-choi ๋‹˜๊ป˜์„œ ์ œ๊ณตํ•ด์ฃผ์‹  ํ•ด๊ฒฐ์ฑ…์„ ๊ณต์œ ํ•ฉ๋‹ˆ๋‹ค.

์˜ค๋ฅ˜ ๋ฐœ์ƒ

์˜ค๋ฅ˜ ํ•ด๊ฒฐ

SkiaSharp์„ ์‚ฌ์šฉํ•˜์‹œ๋Š” ๋ถ„๋“ค๊ป˜ ๋„์›€์ด ๋˜๋ฉด ์ข‹๊ฒ ์Šต๋‹ˆ๋‹ค.

์ข‹์•„์š” 4

์š”๊ฑฐ ๊ฐœ์ธ์ ์œผ๋กœ ๊ถ๊ธˆํ•œ ๋ถ€๋ถ„์ธ๋ฐ, ManagedStream ์‚ฌ์šฉ์ด ํ•ต์‹ฌ์ธ ๊ฑด๊ฐ€์š”โ€ฆ?

์ข‹์•„์š” 2

๊ทธ๋Ÿฐ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค. ์ €๋„ ์™œ ๊ทธ๋Ÿฐ์ง€๋Š” ํŒŒ์•…ํ•˜์ง€ ๋ชปํ–ˆ๊ณ  ์•Œ๋ ค์ฃผ์‹ ๋Œ€๋กœ ์ˆ˜ํ–‰ํ•œ ๋ถ€๋ถ„์ด๋ผโ€ฆ

๊ธฐ์–ต์€ ์ž˜ ์•ˆ๋‚˜์ง€๋งŒ ์–ด๋Š ๊ธ€์—์„ ๊ฐ€ SkManagedStream์€ ์“ฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค๊ณ  SkiaSharp ๊ฐœ๋ฐœ์ž๊ฐ€ ์ผ๋˜ ํฌ์ŠคํŠธ๋ฅผ ๋ดค๋˜ ๊ฒƒ ๊ฐ™์•„์„œ ๊ทธ๋™์•ˆ SkManagedStream ์—†์ด ์‚ฌ์šฉํ–ˆ์—ˆ๋Š”๋ฐ @evan-choi ๋‹˜๊ป˜์„œ ๋ง์”€ํ•ด์ฃผ์‹  ๊ฑดโ€ฆimagebytes ์Šคํƒ์ด ํ•ด์ œ๋˜๋ฉด์„œ unsafe memory์— ์˜ํ–ฅ์ด ์ƒ๊ธด ๊ฒƒ ๊ฐ™์œผ๋‹ˆ SkMangedStream์„ ์จ๋ณด๋ผ๊ณ  ํ•˜์…จ์Šต๋‹ˆ๋‹ค.

SKBitmap.Decode์—์„œ๋“œ ์ค‘์—์„œ ReadOnlySpan๋ฅผ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” ๋ฉ”์„œ๋“œ ์˜ค๋ฒ„๋กœ๋”ฉ์˜ ์ฝ”๋“œ์ •์˜๋ฅผ ์ฐพ์•„์„œ ๋ณด์—ฌ์ฃผ์…จ๋Š”๋ฐ ์•„๋ž˜์™€ ๊ฐ™์Šต๋‹ˆ๋‹ค. Decode์ž์ฒด ์ฝ”๋“œ๊ฐ€ ์œ„ํ—˜ํ•˜๊ฒŒ ์ƒ๊ธฐ๊ธด ํ•˜์…จ๋‹ค๊ณ  ํ•˜์…”์„œ SKManagedStream์„ ์ถ”์ฒœํ•˜์…จ์Šต๋‹ˆ๋‹ค.

public static unsafe SKBitmap Decode(ReadOnlySpan<byte> buffer)
{
    fixed (byte* numPtr = &buffer.GetPinnableReference())
    {
        using (SKData data = SKData.Create((IntPtr) (void*) numPtr, buffer.Length))
        {
             using (SKCodec codec = SKCodec.Create(data))
             {
                  return SKBitmap.Decode(codec);
             }
        }
    }
}
์ข‹์•„์š” 2