实现从内存加载Pyd模块的Python导入器时遇到崩溃问题求助
我之前也折腾过类似的内存加载Pyd模块的需求,Python 3.11的底层加载逻辑变化确实容易踩坑,你遇到的调用PyInit_x后崩溃的问题,大概率是PE加载后的Python特定初始化环节没处理到位,给你几个排查和解决的方向:
检查PE加载后的符号绑定与重定位
你用的那个内存加载库可能只完成了PE文件的基础内存映射和重定位,但Pyd作为Python扩展模块,需要和当前Python运行时的核心符号(比如PyMem_RawAlloc、PyType_Ready这类)正确绑定。Python 3.11引入了PEP 684相关的加载逻辑调整,内存加载时如果没把模块里的导入符号重定向到当前进程的Python运行时地址,就会触发崩溃。建议你手动校验加载后的模块中,所有Python相关的导入符号是否指向了正确的内存地址,而非原Pyd文件的硬编码位置。确保模块初始化的上下文正确
直接调用PyInit_x和Python原生import流程的最大区别在于,原生导入会先准备好模块命名空间、错误处理上下文,并且确保当前线程持有GIL。你可以尝试先通过PyModule_Create创建一个空的模块对象,再把PyInit_x返回的模块字典合并进去,模拟原生导入的上下文环境,再使用模块内容。排查Python 3.11的兼容性问题
那个内存加载库可能没有适配Python 3.11的扩展模块格式。3.11对PyModuleDef结构的细节、模块加载的校验逻辑都有调整,如果库的代码还是基于旧版本Python的PE加载逻辑,就容易出现崩溃。你可以先换Python 3.10测试,如果能正常运行,那就是版本兼容性问题,需要修改内存加载库的代码来适配3.11的要求。通过调试器定位崩溃根源
最直接的方式是用WinDbg或者Visual Studio附加到Python进程,查看崩溃时的调用栈。如果是访问违例,大概率是某个全局变量(比如字符串常量、函数指针)还指向原Pyd文件的磁盘地址,而非内存中的映射地址——这类问题需要在内存加载后手动修正所有需要重定位的非标准PE字段。
备注:内容来源于stack exchange,提问作者orah1998

