批判这段代码:内存映射文件

一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / Java 学习路线 / 一对一提问 / 学习打卡/ 赠书活动

目前,正在 星球 内带小伙伴们做第一个项目:全栈前后端分离博客项目,采用技术栈 Spring Boot + Mybatis Plus + Vue 3.x + Vite 4手把手,前端 + 后端全栈开发,从 0 到 1 讲解每个功能点开发步骤,1v1 答疑,陪伴式直到项目上线,目前已更新了 204 小节,累计 32w+ 字,讲解图:1416 张,还在持续爆肝中,后续还会上新更多项目,目标是将 Java 领域典型的项目都整上,如秒杀系统、在线商城、IM 即时通讯、权限管理等等,已有 870+ 小伙伴加入,欢迎点击围观

我们在生产中的以下代码中遇到错误。我们正在努力确保我们有良好的错误,这使我们能够轻松地解决问题。

在这种情况下,代码……并不是很有帮助。为什么?看看代码,我将在下面解释原因……


 public CodecIndexInput(FileInfo file, Func<Stream, Stream> applyCodecs)
{
    try
    {
        this.file = file;
        this.applyCodecs = applyCodecs;
    fileHandle = Win32NativeFileMethods.CreateFile(file.FullName,
        Win32NativeFileAccess.GenericRead,
        Win32NativeFileShare.Read | Win32NativeFileShare.Write | Win32NativeFileShare.Delete,
        IntPtr.Zero,
        Win32NativeFileCreationDisposition.OpenExisting,
        Win32NativeFileAttributes.RandomAccess,
        IntPtr.Zero);

    if (fileHandle.IsInvalid)
    {
        const int ERROR_FILE_NOT_FOUND = 2;
        if (Marshal.GetLastWin32Error() == ERROR_FILE_NOT_FOUND)
            throw new FileNotFoundException(file.FullName);
        throw new Win32Exception();
    }

    mmf = Win32MemoryMapNativeMethods.CreateFileMapping(fileHandle.DangerousGetHandle(), IntPtr.Zero, Win32MemoryMapNativeMethods.FileMapProtection.PageReadonly,
        0, 0, null);
    if (mmf == IntPtr.Zero)
    {
        throw new Win32Exception();
    }

    basePtr = Win32MemoryMapNativeMethods.MapViewOfFileEx(mmf,
        Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read,
        0, 0, UIntPtr.Zero, null);
    if (basePtr == null)
        throw new Win32Exception();

    stream = applyCodecs(new MmapStream(basePtr, file.Length));
}
catch (Exception)
{
    Dispose(false);
    throw;
}

}

你看见了吗?

此代码有多个位置可以引发 Win32Exception。问题在于,此模式下的 Win32Exception 几乎只是一段代码,我们在该方法中有多个位置可以抛出。

发生这种情况时,如果我们没有部署 PDB 文件,我们无法仅从堆栈跟踪(没有行号)知道是哪个方法调用导致了错误。这会在事后导致一些混乱。

我们通过为每个选项添加描述文本来解决这个问题,包括让我们知道发生了什么的附加信息。特别是,我们不仅包括失败的操作,更重要的是,我们包括失败的文件。