最近在写一个程序时,发现MapViewOfFileEx()有返回487错误的问题。
最初的想法是在程序启动时立即申请一块内存,直到程序退出前都保留这块内存以供自己使用。VirtualAlloc()函数传入MEM_RESERVE,申请成功。VirtualAlloc()函数传入MEM_COMMIT,分配成功。但是当我试图把这个申请到的地址传入MapViewOfFileEx()函数的最后一个参数时,无论如何都是返回失败,GetLastError()返回值必定是487(试图访问无效的地址)。
最大的坑,就在于微软对MapViewOfFileEx()函数的参数lpBaseAddress的说明存在严重误导。
要求lpBaseAddress指向的地址是内存分配粒度的整数倍。OK,VirtualAlloc()函数返回的是65536(64KB)的整数倍地址,满足了。
但是,什么叫“可能现在这个地址是安全的,但不能保证随后这个地址一直是安全的”?
这个坑挖的有点深,它完美的混淆了“可分配地址“和“可使用地址”。MapViewOfFileEx()函数的参数lpBaseAddress指向的地址是:未被分配的、未被使用的。也就是这个地址必须是“自由的”(相当于new关键词都有可能会返回这个地址)。
只要lpBaseAddress参数指向的地址被使用(对于VirtualAlloc()函数来说,无论是MEM_COMMIT还是MEM_RESERVE),就是无效地址。lpBaseAddress参数指向的内存必须是MEM_FREE属性。
What the f..k???合着,我还必须传一个非法指针了?
MapViewOfFileEx()函数正确的理解是:操作系统在进程的私有内存空间中查找一块可以容纳映射目标的内存,找到之后再映射,并返回这块内存的基地址。调用者只能“建议”操作系统在某个未被分配的内存区域进行映射。
VirtualAlloc()函数无法与MapViewOfFileEx()函数配合使用。
随便说一下,通过MapViewOfFile()和MapViewOfFileEx()函数返回的基地址(对应的内存块),其内存属性包含MEM_MAPPED,但这个属性无法人为指定。