如何在WinDbg调试pyx代码时查看变量值?
在WinDbg中调试Cython代码:查看本地变量与PyObject内容
查看Cython本地变量(如min_bound)的数值
WinDbg的自动变量面板对Cython生成的封装变量支持不足,需通过手动命令查看:
- 确认变量的C别名:Cython会将pyx中的变量转换为带
__pyx_v_前缀的C变量(例如min_bound对应__pyx_v_min_bound)。可通过查看Cython生成的.c文件,或在断点处执行x helloworld!__pyx_v_*命令列出所有本地变量。 - 查看变量值:
- 对于基础类型(int/float等),直接执行
dt __pyx_v_min_bound; - 若需明确类型,可指定类型参数:
dt int __pyx_v_min_bound; - 也可使用
dv命令列出当前栈帧的所有变量,定位目标变量后查看其值。
- 对于基础类型(int/float等),直接执行
查看PyObject类型对象(如__pyx_v_self)的内容
要实现类似Python中print(__pyx_v_self)的效果,可通过WinDbg调用Python的调试接口完成:
方法1:调用PyObject_Print函数
- 获取PyObject的指针地址:执行
dt __pyx_v_self得到变量的内存地址(例如0x0000023456789abc)。 - 调用Python的打印函数:
注意:.call python311!PyObject_Print(0x0000023456789abc, &stdout, 0)python311需替换为你实际使用的Python版本模块名(如python39、python310)。
方法2:执行Python代码片段
通过PyRun_SimpleString直接执行Python打印逻辑,将C中的PyObject指针映射到Python环境:
.call python311!PyRun_SimpleString("import ctypes; obj = ctypes.cast(0x0000023456789abc, ctypes.py_object).value; print(obj)")
将0x0000023456789abc替换为__pyx_v_self的实际地址即可。
方法3:使用WinDbg Python扩展(pycmd)
如果安装了WinDbg的Python扩展,可直接用pycmd执行Python代码:
pycmd import ctypes; print(ctypes.cast(0x0000023456789abc, ctypes.py_object).value)
最小示例
操作步骤
- 创建以下三个文件
- 执行编译命令:
python setup.py build_ext --inplace - 运行
main.py确认代码可执行 - 在WinDbg中启动
python.exe - 在Python交互环境中执行:
import os; os.chdir("你的代码文件夹路径"),再粘贴main.py中的代码并回车 - 在WinDbg中打开
helloworld.pyx文件,设置断点 - 再次执行
main.py中的代码触发断点
helloworld.pyx
from __future__ import print_function def fib(n): """Print the Fibonacci series up to n.""" a, b = 0, 1 while b < n: print(b, end=' ') a, b = b, a + b print() def primes(int nb_primes): cdef int n, i, len_p cdef int[1000] p if nb_primes > 1000: nb_primes = 1000 len_p = 0 # 当前p中的元素数量 n = 2 while len_p < nb_primes: # 判断n是否为质数 for i in p[:len_p]: if n % i == 0: break # 如果循环没有break,说明是质数 else: p[len_p] = n len_p += 1 n += 1 # 将结果复制到Python列表 result_as_list = [prime for prime in p[:len_p]] return result_as_list class MyClass: def __init__(self, n) -> None: self.fib = fib(n) self.primes = primes(n) # 尝试在Windbg中查看self.fib和self.primes的值
setup.py
from setuptools import Extension, setup from Cython.Build import cythonize extensions = [Extension('helloworld', ["helloworld.pyx"], extra_compile_args=["-Ox", "-Zi"], extra_link_args=["-debug:full"])] setup( ext_modules = cythonize(extensions, gdb_debug=True, emit_linenums=True) )
main.py
import helloworld my_class = helloworld.MyClass(2000) print(my_class.fib)
内容的提问来源于stack exchange,提问作者codeDom
相关产品推荐
相关产品推荐

