32位程序创建共享内存,64位进程OpenFileMapping返回错误2
问题分析与解决方案
核心原因:WOW64命名空间隔离
Windows的WOW64子系统会对32位和64位进程的命名内核对象(如文件映射)做隔离处理。默认情况下:
- 32位进程创建的命名文件映射会被放置在WOW64专属命名空间(
\Sessions\<会话ID>\BaseNamedObjects\WOW64) - 64位进程默认访问的是原生命名空间(
\Sessions\<会话ID>\BaseNamedObjects)
这种隔离直接导致64位进程无法直接找到32位进程创建的未指定全局命名空间的共享内存对象。
为什么测试程序可以正常工作?
测试程序代码无额外上下文干扰(如UAC虚拟化、会话差异、编码宏冲突),而你的原64位程序存在隐性的环境或代码逻辑问题。
具体排查与解决步骤
1. 强制使用全局命名空间前缀修改共享内存名称
修改32位程序创建共享内存的名称,添加Global\前缀,同时64位程序打开时也使用相同前缀:
// 32位程序创建共享内存 const char* name = "Global\\ProcServSM"; HANDLE hFile = ::CreateFileMappingA(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, name); // 64位程序打开共享内存 const char* name = "Global\\ProcServSM"; HANDLE hFile = ::OpenFileMappingA(FILE_MAP_ALL_ACCESS, TRUE, name);
注意:使用
Global\前缀需要进程拥有SeCreateGlobalPrivilege权限,普通桌面进程默认具备该权限,但服务进程可能需要额外配置权限。
2. 排查编码宏冲突
确认原64位程序及依赖库中是否意外定义了_UNICODE或UNICODE宏:
- 若代码使用
TCHAR或隐式调用CreateFileMapping/OpenFileMapping(未加A后缀),当64位程序定义了UNICODE宏,会自动调用宽字符版本(CreateFileMappingW),而32位程序用的是ANSI版本(CreateFileMappingA),导致名称编码不匹配。 - 解决方式:统一使用显式的ANSI版本函数(
CreateFileMappingA、OpenFileMappingA),确保名称字符串编码完全一致。
3. 检查UAC虚拟化与权限上下文
- 确认32位程序和64位程序是否运行在同一权限级别(如均为普通用户或均为管理员)。若权限级别不同,UAC虚拟化会隔离命名对象。
- 临时验证:右键程序属性→兼容性→勾选「禁用UAC虚拟化」,重新运行程序测试。
4. 确认会话一致性
若32位程序是服务进程(运行在Session 0),64位程序是桌面进程(运行在Session 1及以上),默认的Local\命名空间对象无法跨会话访问,必须使用Global\前缀。
5. 验证名称变量的一致性
检查原64位程序中使用的共享内存名称是否与32位程序完全一致:
- 排查是否在名称中拼接了进程ID、路径或其他动态值,导致实际名称不匹配。
- 用Process Explorer工具验证:找到32位进程→右键属性→Handles→查找类型为
Section的对象,查看其实际名称,与64位程序使用的名称对比。
内容的提问来源于stack exchange,提问作者user3407352
相关产品推荐
相关产品推荐

