Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/303.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用ctypes模块和GDB会话更改内存中的Python整数_Python_C_Gdb_Ctypes - Fatal编程技术网

使用ctypes模块和GDB会话更改内存中的Python整数

使用ctypes模块和GDB会话更改内存中的Python整数,python,c,gdb,ctypes,Python,C,Gdb,Ctypes,我的问题基于reddit post。该示例显示了如何使用ctypes模块中的cast函数更改内存中的整数: >>> import ctypes >>> ctypes.cast(id(29), ctypes.POINTER(ctypes.c_long))[3] = 100 >>> 29 100 我对这里的底层内部结构感兴趣,我在GDB会话中通过在CPython中的cast函数上设置断点来检查这一点: (gdb) break cast Func

我的问题基于reddit post。该示例显示了如何使用
ctypes
模块中的
cast
函数更改内存中的整数:

>>> import ctypes
>>> ctypes.cast(id(29), ctypes.POINTER(ctypes.c_long))[3] = 100
>>> 29
100
我对这里的底层内部结构感兴趣,我在GDB会话中通过在
CPython
中的
cast
函数上设置断点来检查这一点:

(gdb) break cast
Function "cast" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 1 (cast) pending.
(gdb) run test.py 
Starting program: /root/.pyenv/versions/3.8.0-debug/bin/python test.py
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
0x7ffff00e7b40

Breakpoint 1, cast (ptr=0x9e6e40 <small_ints+1088>, src=10382912, ctype=<_ctypes.PyCPointerType at remote 0xa812a0>) at /root/.pyenv/sources/3.8.0-debug/Python-3.8.0/Modules/_ctypes/_ctypes.c:5540
5540        if (0 == cast_check_pointertype(ctype))
(gdb) p *(PyLongObject *) ptr
$38 = {
  ob_base = {
    ob_base = {
      ob_refcnt = 12, 
      ob_type = 0x9b8060 <PyLong_Type>
    }, 
    ob_size = 1
  }, 
  ob_digit = {100}
}
(gdb) p *((long *) ptr + 3)
$39 = 100
(gdb) p ((long *) ptr + 3)
$40 = (long *) 0x9e6e58 <small_ints+1112>
(gdb) p *((char *) ptr + 3 * 8)
$41 = 100 'd'
(gdb) p ((char *) ptr + 3 * 8)
$42 = 0x9e6e58 <small_ints+1112> "d"
(gdb) set *((long *) ptr + 3) = 29
(gdb) p *((long *) ptr + 3)
$46 = 29
(gdb) p *((char *) ptr + 3 * 8)
$47 = 29 '\035'
索引也不同于Python REPL,我想这与endianness有关

(gdb) python print(ctypes.cast(id(29), ctypes.POINTER(ctypes.c_long))[3])
9
(gdb) python print (ctypes.cast(id(29), ctypes.POINTER(ctypes.c_long))[2])
29
问题:

  • 为什么GDB会话中Python的内存地址不可访问,值不在进程内存范围内(
    info proc mappings
  • 为什么索引与Python REPL不同
  • (额外问题)我希望
    CPython
    cast
    函数中的
    src
    参数保存对象的地址,但它似乎是
    ptr
    ,而在
    result->b_ptr
    之后指向与
    &ptr
    不同的值?这是真的吗
  • 您的Python进程不是真正的Python进程,相反,GDB正在为您运行Python REPL。把它想象成GDB中的另一个线程。当然,这是一种简化,你应该看到
  • 我无法重现这种行为:
    (gdb)python
    >导入ctypes
    >打印(ctypes.cast(id(29),ctypes.POINTER(ctypes.c_long))[3])
    >结束
    29
    
    我想不出发生这种行为的任何原因(至少是endianness,它在整个系统中都是一样的*)
  • src
    参数似乎用作原点类型,而不是原点对象。作为参考,请参阅和(\u SimpleData只是CDATA对象,有一些帮助程序,如索引和repr)。是的,memcpy是在这种情况下进行实际转换的工具,尽管如果您在两种数据类型之间进行转换,那么之前还有额外的工作要做
  • *除了在ARM上,您可以通过指令更改端点

    (gdb) python print(ctypes.cast(id(29), ctypes.POINTER(ctypes.c_long))[3])
    9
    (gdb) python print (ctypes.cast(id(29), ctypes.POINTER(ctypes.c_long))[2])
    29