access violation error in Python x64 when using ctypes (caused by pointer)

问题描述

似乎这个问题仅存在于Windows下Python x64中,且Python 2和Python 3中的表现不一致;并且一般是由于调用的C-API包含有指针传递,出现类似如下错误OSError: exception: access violation reading 0x0000000025F0FA60

示例

C++代码:

函数bar()期望完成的是两个字符串的连接。getFoo()返回一个类指针,而getChild()接受一个类指针,返回字符串。

测试一

正常的Python代码:

在Python 2.7.12下执行正确,返回

但在Python 3.5.2下执行会提示错误:

ctypes.string_at(out)出现了非法的内存地址访问。

测试二

正常的Python代码:

在Python 2和Python 3中都会出现非法的内存访问,但出错的语句不一样。

在Python 2.7.12下执行提示错误:

ctypes.string_at(out)出现了非法的内存地址访问。

在Python 3.5.2下执行提示错误:

lib.getChild(foo)出现了非法的内存地址访问。

原因分析

先来看看ctypes.string_at(),在官方文档里给出的描述是ctypes.string_at(address, size=-1)

This function returns the C string starting at memory address address as a bytes object. If size is specified, it is used as size, otherwise the string is assumed to be zero-terminated.

string_at()接受的参数是内存地址,似乎隐约知道出错的原因了:给string_at()传递了一个错误的内存地址,导致程序执行时试图访问非法的内存地址,提示错误。

但传入string_at()的参数是由API直接返回的,怎么会出错呢?继续看官方文档,官方文档中提到在加载动态链接库时Functions in these libraries use the standard C calling convention, and are assumed to return int.

意思就是C-API中任何类型的返回值,在Python中统一都是int,这样也容易理解:返回int类型就是int值,返回指针就是内存地址(毕竟指针实际就是记录内存地址的)。那是不是返回的指针地址就是错的?我们来试试看。

现在打印出返回的内存地址

在Python 3.5.2运行几次,看看返回的内存地址和错误提示的关系

返回的内存地址和非法内存地址访问是一致的!而且内存地址甚至出现了负数,怎么可能!问题就是出在返回指针(即返回内存地址)上面了,无论是char*还是Foo*都有这种问题!

通过测试32位版本的动态链接库,Python 2和Python 3均未出现问题,可以确定是32位和64位兼容性问题,类似于著名的C语言x86和x64下int的长度问题。

注意:限于自己目前的水平,更深层次的原因还不得而知,但需要注意Python2和Python3下出错的表现不一致,Python2下似乎可以克服一些指针传递问题。

解决方法

通过多次尝试,我发现可以通过设置API的restype来获得正确的内存地址。

restype可以重载API的返回值类型(记得上面说的默认值为int吧),因为64位下内存地址为64位无符号型整数,因此设置为ctypes.c_uint64。由于修改了返回值类型,在指针作为函数调用的输入参数时,也可能要作出对应的类型转换。

修正后的测试一

Python 2.7.12和Python 3.5.2均能得到正确结果。

修正后的测试一

Python 2.7.12和Python 3.5.2均能得到正确结果。

小结

如上提到的解决方法只能算作临时的修补,我更倾向于认为这是Python自身的一个bug:没有解决64位环境下的C指针类型问题。

参考

python access violation_Python x64下ctypes动态链接库出现access violation的原因分析相关推荐

  1. lnux php 连接access,在Linux下实现对Microsoft Access Database(.mdb

    在Linux下实现对Microsoft Access Database(.mdb [ 网络作者:佚名 更新时间:2009-02-23 | 字体:大 中 小] [导读]You will need the ...

  2. win10下scapy get_working_if()不能获得正确的网卡原因分析

    问题 Environment :Win10, python 3.7 and scapy 2.4.3 路由表如下所示, ZeroTier是一个虚拟内网接口,I219是外网接口. 明显I219的Metri ...

  3. Linux下sqlite3乱码,sqlite中文乱码问题原因分析及解决

    在VC++中通过sqlite3.dll接口对sqlite数据库进行操作,包括打开数据库,插入,查询数据库等,如果操作接口输入参数包含中文字符,会导致操作异常.例如调用sqlite3_open打开数据库 ...

  4. 关于“python无法定位序数242于动态链接库: libiomp5md.dll”问题的解决

    在Windows操作系统下,针对Anaconda环境,使用命令行模式调用python时,可能出现"python无法定位序数xxx于动态链接库: xxx.dll"问题,原因: 系统中 ...

  5. access创建窗体特别慢_64位Access运行速度很慢的解决办法

    在64位的Window 7,winows10,Windows 2012中, Access运行很慢的解决方案: 有遇到一个很奇怪的问题,将以前在window 10 Access 32位下开发的一个Acc ...

  6. c调用python第三方库_Python使用ctypes模块调用DLL函数之C语言数组与numpy数组传递...

    在Python语言中,可以使用ctypes模块调用其它如C++语言编写的动态链接库DLL文件中的函数,在提高软件运行效率的同时,也可以充分利用目前市面上各种第三方的DLL库函数,以扩充Python软件 ...

  7. python关联通达信pywin32_Python ctypes.wintypes方法代码示例

    本文整理汇总了Python中ctypes.wintypes方法的典型用法代码示例.如果您正苦于以下问题:Python ctypes.wintypes方法的具体用法?Python ctypes.wint ...

  8. c#(winform)环境下使用动态链接库dll的详解

    c#(winform)环境下使用动态链接库dll的详解 转载 2016年05月14日 10:12:17 3208 1,什么是dll文件? DLL(Dynamic Link Library)文件为动态链 ...

  9. [系统底层] x86和x64下ssdt的差异

    2019独角兽企业重金招聘Python工程师标准>>> X86和x64下ssdt的差异 首先介绍一下SSDT相关的结构体 PVOID无类型指针,x86下32位,x64下64位 结构体 ...

最新文章

  1. ABA问题的本质及其解决办法
  2. 找到一本适合自己的SQL Server 2008入门书
  3. Opencv 去高光或镜面反射(illuminationChange)
  4. Java 8新特性终极指南
  5. Java基础提升篇:equals()与hashCode()方法详解
  6. 可以直接进行运算么_WORD办公技巧:如何直接在WORD中进行加法、乘法运算?
  7. GridView控件 72变(一)
  8. Python使用Apriori算法查找关系密切的演员组合
  9. 3说明书_怎么才能做好产品说明书翻译?知行翻译公司总结了3点
  10. Rust 第一章 简介
  11. 人机交互论文计算机导论,计算机导论第10章人机交互[精].ppt
  12. 2018上半年广东省中小学教师资格认定流程
  13. SNOWNLP情感分析报错解决
  14. 9大最佳知识库软件/文档管理工具
  15. 高等数学与计算机的关联论文,高等数学改革管理计算机信息论文
  16. 教你怎么用三种办法找到发给你QQ的坦白说的那个人
  17. 把桌面路径改到D盘,忘记新建文件夹,D盘所有文件跑到桌面怎么办?
  18. 10天竟然只写了一行代码,谁的锅?
  19. html 的smap标签,SMap.Label
  20. [论文笔记]Feature-constrained Active Visual SLAM for Mobile Robot Navigation

热门文章

  1. 苹果6用U盘越狱_iOS 13 Checkra1n Win 越狱新方法,超级简单
  2. C# 使用Emit深克隆
  3. 大数据下的用户画像标签去重
  4. 西瓜视频怎么做伪原创
  5. B站硬核up主稚晖君:对于有志学习嵌入式开发的软件工程师,我有这些建议!...
  6. Vue nvm重装node和npm与vue3报错Emitted ‘error‘ event on ChildProcess instance at errno: -4058
  7. SpringBoot-logback配置输出Json格式日志
  8. QtCreator-----Kits选项选择
  9. 关于 DRM 中 DUMB 和 PRIME 名字的由来
  10. python+pytest接口自动化之测试函数、测试类/测试方法的封装