MapViewOfFile映射文件块到内存失败,GetLastError返回0x46c的问题。

    m_hFile = m_file.m_hFile;
	ULONGLONG dwFileSize = GetFileSize(m_hFile, NULL);
	//得到的系统页大小是4k,但大文件映射部分块需要偏移以64k对齐。
	m_SyspageSize = 65536;
	 定义映射的起始偏移和映射的大小
	ULONGLONG UllOffset = dwNodeIndex * 0x640 + m_dwFnmOffset + sizeof(DirFileTreeHead);
	UllOffset = (UllOffset / m_SyspageSize) * m_SyspageSize;

	DWORD dwSizeToMap = 65536;
	//dwSizeToMap = dwSizeToMap / m_SyspageSize * m_SyspageSize;
	m_hMapping = CreateFileMapping(
		m_hFile,
		NULL,
		PAGE_READWRITE,
		HIDWORD(dwFileSize),
		LODWORD(dwFileSize),
		NULL);
	m_lpFile = (BYTE*)MapViewOfFile(
		m_hMapping,
		FILE_MAP_READ | FILE_MAP_WRITE,
		HIDWORD(UllOffset),
		LODWORD(UllOffset),
		dwSizeToMap + 0x640);//一个节点的大小为0x640,
	DWORD dwError = GetLastError();
	DWORD dwError1 = dwError;

最近写项目时使用文件映射遇到的一个问题。在映射大文件时,并不能一次将全部文件映射到内存中,毕竟内存空间有限^_^,所以需要分块映射,幸好“万能的微软”肯定已经考虑了这个问题的,我们可以通过改变MapViewOfFile的参数来设置需要映射文件的偏移和指定大小,但问题就出在参数的问题上,它并不是能够任意去指定的,需要以系统页大小去对齐。微软官方文档是这么解释的,英文文档我也看过,是一样的解释。那么让我们看看SYSTEM_INFO的结构和什么是系统的内存分配粒度。

typedef struct _SYSTEM_INFO {
  union {
    DWORD dwOemId;
    struct {
      WORD wProcessorArchitecture;
      WORD wReserved;
    } DUMMYSTRUCTNAME;
  } DUMMYUNIONNAME;
  DWORD     dwPageSize;
  LPVOID    lpMinimumApplicationAddress;
  LPVOID    lpMaximumApplicationAddress;
  DWORD_PTR dwActiveProcessorMask;
  DWORD     dwNumberOfProcessors;
  DWORD     dwProcessorType;
  DWORD     dwAllocationGranularity;
  WORD      wProcessorLevel;
  WORD      wProcessorRevision;
} SYSTEM_INFO, *LPSYSTEM_INFO;

主要看dwPageSize这个参数,文档是这么说的。

那么问题好像就解决了,呵呵呵呵。所以想当然的我使用dwPageSize做了偏移对齐。结果每次只有第一次MapViewOfFile返回的指针是有值的。哦不.....,我的耐心已经要被消耗完了(看来我的耐心有点差,呵呵呵呵o(* ̄︶ ̄*)o)。根据getlasterror返回的错误码0x46c,进行搜索。 

得到的结果是【0x46c|1132】-指定的基址或文件偏移量没有适当对齐。那就很奇怪啊,明明不就是对齐了吗?进行了自我怀疑,就这么几行破代码又看又改(he,tui)。直到看见了

内存映射文件 错误码(1132、5)_getlasterror 1132_xian_wwq的博客-CSDN博客

用MapViewOfFile处理大文件-内存不足_mapviewoffile指定读取的起始位置_滴水梵音的博客-CSDN博客z

这两篇博客,原来对齐的应该是

  SYSTEM_INFO sinf;

  GetSystemInfo(&sinf);

  DWORD dwAllocationGranularity = sinf.dwAllocationGranularity;这个参数。

感觉自己试撒币....。问题解决,偏移应该是以64k对齐。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
是的,你说得对。Windows API中的CreateFileMapping函数和MapViewOfFile函数可以用来将一个文件映射到进程的虚拟地址空间中。这两个函数的原型分别如下: ``` HANDLE CreateFileMapping( HANDLE hFile, LPSECURITY_ATTRIBUTES lpAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCTSTR lpName ); LPVOID MapViewOfFile( HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap ); ``` 其中,CreateFileMapping函数用于创建一个文件映射对象,它的参数包括文件句柄hFile、保护属性flProtect、最大文件映射大小等;MapViewOfFile函数用于将文件映射到进程的虚拟地址空间中,它的参数包括文件映射对象句柄hFileMappingObject、映射的起始地址等。 具体来说,我们可以使用CreateFileMapping函数创建一个文件映射对象,然后使用MapViewOfFile函数将文件映射到进程的虚拟地址空间中。比如,我们可以使用以下代码将一个遥感图像文件映射内存中: ``` HANDLE hFile = CreateFile( "test.img", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL ); HANDLE hMapFile = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL ); LPBYTE pImage = (LPBYTE)MapViewOfFile( hMapFile, FILE_MAP_READ, 0, 0, 0 ); ``` 在这段代码中,我们首先使用CreateFile函数打开一个遥感图像文件,然后使用CreateFileMapping函数创建一个文件映射对象,并将其关联到文件句柄hFile上。最后,使用MapViewOfFile函数将文件映射到进程的虚拟地址空间中,并返回映射的起始地址pImage。 需要注意的是,当使用完毕后,需要使用UnmapViewOfFile函数将文件映射从进程的虚拟地址空间中解除映射,并使用CloseHandle函数关闭文件句柄和文件映射对象句柄,以释放资源。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值