从Resources加载图片在Release模式下触发原生崩溃求助
MAUI类库嵌入图片Release模式崩溃问题
根据微软文档,加载嵌入图片的代码如下:
Assembly assembly = GetType().GetTypeInfo().Assembly; using Stream stream = assembly.GetManifestResourceStream("Ringotan.KanjiControl.Resources.next_arrow.png"); _arrowImage = PlatformImage.FromStream(stream);
这段代码在Debug模式下运行完全正常,但在Release模式下会触发原生SIGSEGV崩溃,崩溃栈信息如下:
[libc.so] __memcpy_aarch64_simd SIGSEGV backtrace: #00 pc 0x0000000000058158 /apex/com.android.runtime/lib64/bionic/libc.so (__memcpy_aarch64_simd+280) #01 pc 0x000000000065bd04 /system/lib64/libhwui.so ((anonymous namespace)::FrontBufferedStream::read(void*, unsigned long) (.__uniq.259476571162685252206752541612201816602)+340) #02 pc 0x000000000065bd60 /system/lib64/libhwui.so ((anonymous namespace)::FrontBufferedStream::peek(void*, unsigned long) const (.__uniq.259476571162685252206752541612201816602)+48) #03 pc 0x00000000005b4168 /system/lib64/libhwui.so (SkCodec::MakeFromStream(std::__1::unique_ptr<SkStream, std::__1::default_delete<SkStream>>, SkSpan<SkCodecs::Decoder const>, SkCodec::Result*, SkPngChunkReader*, SkCodec::SelectionPolicy)+120)
这是原生崩溃,无法通过.NET异常捕获机制处理。
问题:是否有解决该崩溃的方法?如果没有,有没有更好的加载IImage的方式?
背景信息
- 资源和代码均位于MAUI类库中,而非主MAUI应用项目;尝试从类库加载主项目的嵌入资源无法正常工作。
- 资源已正确设置为「Build Action: Embedded Resource」。
- 已禁用AOT和Trimming,问题依然存在。
- Debug模式下代码正常运行,确认资源流名称正确。
解决方案与替代方案
1. 修复当前崩溃的方法
问题根源是using语句会在PlatformImage.FromStream调用后立即释放流,但部分平台的PlatformImage可能不会立即完成流读取,导致后续原生代码访问已释放的内存。可以尝试两种修复方式:
方式一:移除using声明,手动管理流生命周期
Assembly assembly = GetType().GetTypeInfo().Assembly; Stream stream = assembly.GetManifestResourceStream("Ringotan.KanjiControl.Resources.next_arrow.png"); _arrowImage = PlatformImage.FromStream(stream); // 注意:部分平台会接管流的生命周期,无需手动关闭;若需释放,需确认图片加载完成后操作
方式二:将流复制到内存流中
通过内存流保留完整数据,避免原流被提前释放:
Assembly assembly = GetType().GetTypeInfo().Assembly; using Stream originalStream = assembly.GetManifestResourceStream("Ringotan.KanjiControl.Resources.next_arrow.png"); using MemoryStream memoryStream = new MemoryStream(); originalStream.CopyTo(memoryStream); memoryStream.Position = 0; _arrowImage = PlatformImage.FromStream(memoryStream);
2. 更可靠的IImage加载方式
推荐使用MAUI内置的稳定API替代直接调用PlatformImage:
方式一:使用ImageSource.FromResource
var imageSource = ImageSource.FromResource("Ringotan.KanjiControl.Resources.next_arrow.png", typeof(YourClass).GetTypeInfo().Assembly); using var stream = await imageSource.GetStreamAsync(); _arrowImage = PlatformImage.FromStream(stream);
方式二:使用BitmapImage.LoadAsync(.NET MAUI 8+)
这是官方推荐的跨平台API,内部已处理流生命周期和兼容性:
Assembly assembly = typeof(YourClass).GetTypeInfo().Assembly; using Stream stream = assembly.GetManifestResourceStream("Ringotan.KanjiControl.Resources.next_arrow.png"); _arrowImage = await BitmapImage.LoadAsync(stream);
内容的提问来源于stack exchange,提问作者BlueRaja - Danny Pflughoeft
相关产品推荐
相关产品推荐

