Python内存地址:Linux上Python 3.5和3.9之间的差异

2024-09-28 05:21:35 发布

您现在位置:Python中文网/ 问答频道 /正文

我偶然发现了一个令人困惑的问题。在尝试使用ctypes.CDLL("libX11.so")热修复VTK手动关闭XDisplay时,我尝试使用Python提供的XDisplay地址。这在Python3.8上运行良好,但在Python3.7上导致了一个错误。下面的代码演示如何解决在VTK中创建的XDisplay的问题。具体而言:

disp_id = self.ren_win.GetGenericDisplayId()
disp_id_int = int(disp_id[1:].split('_')[0], 16)
print(disp_id, disp_id_int)
x11 = ctypes.CDLL("libX11.so")
x11.XCloseDisplay(disp_id_int)

当运行时,返回:

user@host:~/tmp$ python3.7 tmp19.py
0000558f843c5930_p_void 94074887231792
Current thread 0x00007f8145824740 (most recent call first):
  File "/home/alex/python/pyvista/pyvista/plotting/plotting.py", line 2769 in close
  File "/home/alex/python/pyvista/pyvista/plotting/plotting.py", line 4207 in show

user@host:~/tmp$ python3.8 tmp19.py
0000000003568de0_p_void 56004064

如您所见,Python3.8中的地址可以与libX11.so一起使用,但不能与Python3.7一起关闭XDisplay窗口

如注释中所述,Python返回的内存地址始终与当前Python进程相关。但是,如果是这种情况,为什么某些版本的Python会返回非常大的id(True)地址,这是Python初始化时创建的结构。更令人困惑的是,返回这些大值的Python版本在与"libX11.so"库接口时也会产生分段值

以下是Python 3.5-Python 3.9的结果:

user@host:~$ python3.5 -c "print(id(True))"
93962585975264
user@host:~$ python3.6 -c "print(id(True))"
10302848
user@host:~$ python3.7 -c "print(id(True))"
94134164615424
user@host:~$ python3.8 -c "print(id(True))"
11498848
user@host:~$ python3.9 -c "print(id(True))"
11374464

两个问题:

  • 这是预期的行为吗?如果是这样的话,我想对于我在本地安装的版本,有一个编译器标志被打开/关闭
  • 是否有一种方法可以调整内存地址,从而为所有版本的Python获得一致的结果

Tags: py版本idtruehostso地址plotting
2条回答

结果表明,问题在于指针为>;在我的64位Linux环境中使用4GB,这与使用ctypes包装库时的默认行为不兼容。重复@MarkTolonen的评论:

as the parameter type will pass the value incorrectly on 64-bit systems. ctypes assumes 32-bit integers for integer parameters unless told otherwise

诀窍是将argtype设置为c_void_p

x11 = ctypes.CDLL("libX11.so")
x11.XCloseDisplay.argtypes = [ctypes.c_void_p]
x11.XCloseDisplay(disp_id_int)

在Python3.8上,这对我有效的原因是指针的地址恰好小到可以作为int32传递,而在Python3.7上,正好整数对于int32太大。相反,将其作为ctypes.c_void_p传递解决了这个问题

取决于cpython implementation detailid(...)函数返回PyObject的内存地址

在cpython中,Py_TruePy_Falsemacros, pointing at global instances of ^{} structs

/* Use these macros */
#define Py_False ((PyObject *) &_Py_FalseStruct)
#define Py_True ((PyObject *) &_Py_TrueStruct)

实际的definition of these structs

/* The objects representing bool values False and True */

struct _longobject _Py_FalseStruct = {
    PyVarObject_HEAD_INIT(&PyBool_Type, 0)
    { 0 }
};

struct _longobject _Py_TrueStruct = {
    PyVarObject_HEAD_INIT(&PyBool_Type, 1)
    { 1 }
};

C全局变量的内存地址由编译器、链接器和动态加载程序确定,根据常量值存在未定义的行为

相关问题 更多 >

    热门问题