我刚开始是把函数
LPVOID MapViewOfFile( 
  HANDLE hFileMappingObject, 
  DWORD dwDesiredAccess, 
  DWORD dwFileOffsetHigh, 
  DWORD dwFileOffsetLow, 
  DWORD dwNumberOfBytesToMap 
);
最后一个参数设为整个文件大小,将整个文件映射进去,运行完程序内存占用高达200多兆,因为在这个程序中,我使用了递归,在递归的每一层都创建两个内存映射文件,一个读,一个写,然后在进入下一层的时候,把两个内存映射对象都close掉,我想是不是内存映射文件创建得太多,或者不应该每次都把整个文件映射进去的缘故。后来我在另一段程序中,我只创建一个写的内存映射对象,然后把上百个文件(每个文件不到1M),一个个写写到这个内存映射对象中,我设置最后一个参数设置的时候,是要写多大数据就设多大,把偏移量dwFileOffsetLow也计算设置好,写完一个文件以后调用UnmapViewOfFile( lpMapAddress ),但是现在每写一个文件就增长2M内存,太恐怖了,写完100个要占用多少啊,我觉得应该是我对内存映射还理解不够,但是网上找了很久,看了很多,但还是那些东西,请那位高手对内存映射很熟悉的,给点指导,谢谢了!!!!

解决方案 »

  1.   

    你确定UnmapViewOfFile中的lpMapAddress 与你MapViewOfFile返回的地址完全一致吗?
      

  2.   

    是不是您用的内存Page呀.如果是递归的问题,你不如用栈来改写程序,不要使用递归试试
      

  3.   

    1.因为我这个程序要处理大数据,必须用内存映射
    2.UnmapViewOfFile中的lpMapAddress是我封装在类中的私用成员,MapViewOfFile直接返回给他,用完以后用UnmapViewOfFile关闭它,然后在写下一个文件的时候,在调用MapViewOfFile返回给 lpMapAddress用完后再用UnmapViewOfFile关闭它,如此循环,循环有上百次3.我上一个程序用的是递归,这个没有用递归,我就想看一下是不是递归的问题,再说递归的时候,在进入下一层的时候,已经close了阿
      

  4.   

    我记得你上次贴出的封装类代码中,lpMapAddress是不断变化的,你是否做了修改?
      

  5.   

    这一次我实例化内存映射对象以后,先在一个成员函数里CreateFile和CreateFileMapping,然后在写数据的时候,在写数据的函数里MapViewOfFile,因此每次写数据的时候都会传进去一个偏移量,然后MapViewOfFile,因此每次写的时候,这个地址都是新的,用完以后就close掉下次写再重复上面的过程,我在写数据的函数里用的是memcpy
      

  6.   

    因此每次写数据的时候都会传进去一个偏移量,然后MapViewOfFile
    ------------------------------------------
    先把上次的UnmapViewOfFile,不要用递归!
      

  7.   

    //写数据的函数,每写一个数据调用一次,n是通过计算要写的数据大小得出来的
    VOID CFileMapping::FileWrite(BYTE* SrcPointer,DWORD n,DWORD FileStart)
    {

    MapHeadAddress = MapViewOfFile(
    hMapFile,           
    FILE_MAP_WRITE,     
    0,                   
    FileStart,      // 从FileStart开始映射
    n);      // 需要影射的大小,从函数传入

     ::memcpy((BYTE*)MapHeadAddress,SrcPointer,n);}//关闭页面的函数,每写完一个数据后就调用它
    VOID CFileMapping::CloseFileView()
    {
    ::UnmapViewOfFile( MapHeadAddress );
    }
      

  8.   


    VOID CFileMapping::FileWrite(BYTE* SrcPointer,DWORD n,DWORD FileStart)
    {
    MapHeadAddress = MapViewOfFile(
    hMapFile,           
    FILE_MAP_WRITE,     
    0,                   
    FileStart,      // 从FileStart开始映射
    n);      // 需要影射的大小,从函数传入

    memcpy((BYTE*)MapHeadAddress,SrcPointer,n);
    UnmapViewOfFile( MapHeadAddress ); //用完后立刻释放
    }
      

  9.   

    1.trueadou(木头龙)大哥,这次跟递归没关系了,是另外一个,因为我这次只创建一个写数据的内存映射对象,我计算了整个文件有多大,然后调用了CreateFilemapping后,就不先不调用MapViewOfFile了2.我现在这个程序是为了把100多个小的文件合成一个大的文件(就是刚才创建的内存映射对象),因为这100多个文件的文件名是用规律的,同通过一个循环,找到这个文件3.找这个文件后,调用类里写文件的函数,在这个函数里有MapViewOfFile,也就是上面我贴出来的函数,这个函数里的DWORD FileStart,就是传进去的偏移量,因为要确定从哪里开始映射
    利用返回的 MapHeadAddress和memcpy写数据4.写完一文件后,就调用上面的CloseFileView()函数关闭页面,5.上面这个循环有100多次
      

  10.   

    用了chehw(chehw) 大哥的方法,遇到了一个新的问题,不知道是什么原因产生的VOID CFileMapping::FileWrite(BYTE* SrcPointer,DWORD n,DWORD FileStart)
    {
    MapHeadAddress = MapViewOfFile(
    hMapFile,           
    FILE_MAP_WRITE,     
    0,                   
    FileStart,      // 这个FileStart如果是0返回的MapHeadAddres正常 ,我第二次调用这个偏移量为84的时候,就不行了,返回为NULL,怎么回事,不是可以随便设定开始映射的位置吗?
    n);      

    memcpy((BYTE*)MapHeadAddress,SrcPointer,n);
    UnmapViewOfFile( MapHeadAddress ); 
    }
      

  11.   

    dwFileOffsetLow须以系统的分页为边界(dwPageSize的整数倍, dwPageSize=4096/8192等)。
    可通过GetSystemInfo取得sysInfo.dwPageSize的大小。
      

  12.   

    这个方法很凑效,内存不增长了VOID CFileMapping::FileWrite(BYTE* SrcPointer,DWORD n,DWORD FileStart)
    {
    MapHeadAddress = MapViewOfFile(
    hMapFile,           
    FILE_MAP_WRITE,     
    0,                   
    FileStart,      // 从FileStart开始映射
    n);      // 需要影射的大小,从函数传入

    memcpy((BYTE*)MapHeadAddress,SrcPointer,n);
    UnmapViewOfFile( MapHeadAddress ); //用完后立刻释放
    }
      

  13.   

    注:上面写错了,应是sysinfo.dwAllocationGranularity
      

  14.   

    文件的偏移地址由DWORD型的参数dwFileOffsetHigh和dwFileOffsetLow组成的64位值来指定,而且必须是操作系统的分配粒度的整数倍,对于Windows操作系统,分配粒度固定为64KB。当然,也可以通过如下代码来动态获取当前操作系统的分配粒度:SYSTEM_INFO sinf;
    GetSystemInfo(&sinf);
    DWORD dwAllocationGranularity = sinf.dwAllocationGranularity; 
      

  15.   

    现在变成偏移值是系统分配粒度的问题了我第二次调用VOID CFileMapping::FileWrite(BYTE* SrcPointer,DWORD n,DWORD FileStart)的时候,因为我上一次只写了84BYTE,因此我这一次要接着这84BYTE网后写,但是用dwFileMapStart = (FileStar / dwSysGran) * dwSysGran后,因为FileStar=84字长(32位),dwSysGran=65563我是不是该用dwFileMapStart = (FileStar *65536/ dwSysGran) * dwSysGran阿????
      

  16.   

    上面说错了,应该是84字节,不是84BYTE
      

  17.   

    dwFileMapStart = (FileStar / dwSysGran) * dwSysGran开始映射
    偏移(FileStar % dwSysGran)开始写