面试题答案
一键面试利用GDB定位和调试Python C扩展模块与Python解释器底层交互错误
- 编译带有调试信息的扩展模块:在编译C扩展模块时,使用
-g
选项,例如:
gcc -g -shared -I$(python3 -c "import sys; print(sysconfig.get_path('include'))") -o mymodule.so mymodule.c
- 启动GDB并加载Python和扩展模块:假设Python可执行文件路径为
/usr/bin/python3
,扩展模块为mymodule.so
,启动GDB:
gdb /usr/bin/python3
(gdb) file /usr/bin/python3
(gdb) break main
(gdb) run your_script_using_mymodule.py
- 捕获段错误:当程序因为内存管理不当等问题出现段错误时,GDB会停止并显示错误发生的位置。例如:
Program received signal SIGSEGV, Segmentation fault.
0x00007ffff7a50997 in PyDict_SetItem () from /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0
- 回溯调用栈:使用
bt
命令查看调用栈,分析是从哪里调用到出错的函数,例如:
(gdb) bt
#0 0x00007ffff7a50997 in PyDict_SetItem () from /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0
#1 0x00007ffff7a5170f in PyDict_SetItemString () from /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0
#2 0x00007ffff7a52213 in PyModule_AddObject () from /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0
#3 0x00007ffff7a526d7 in PyModule_Create2 () from /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0
#4 0x000055555555992e in initmymodule () at mymodule.c:42
#5 0x00007ffff7a52825 in _PyImport_LoadDynamicModuleWithSpec () from /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0
#6 0x00007ffff7a52f8d in _PyImport_LoadModuleObjectWithSpec () from /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0
#7 0x00007ffff7a5379a in _PyImport_ImportWithSpec () from /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0
#8 0x00007ffff7a53c09 in _PyImport_ImportModuleLevelObject () from /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0
#9 0x00007ffff7a53c7f in PyImport_ImportModuleLevel () from /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0
#10 0x00007ffff7a54156 in PyImport_ImportModule () from /usr/lib/x86_64-linux-gnu/libpython3.8.so.1.0
- 检查变量和内存:使用
print
命令查看变量的值,使用x
命令查看内存内容,帮助定位问题。例如:
(gdb) print some_variable
(gdb) x/10xb some_pointer
自定义异常系统设计思路及核心代码示例
- 异常分类:通过继承
BaseException
或Exception
类来创建不同类型的自定义异常类。 - 异常传播控制:在函数内部引发异常,让调用者决定如何处理异常。
- 与Python标准库异常处理机制兼容:确保自定义异常可以被
try - except
语句捕获,与标准异常处理逻辑一致。
核心代码示例:
class CustomError(Exception):
"""自定义异常基类"""
pass
class SpecificCustomError1(CustomError):
"""特定的自定义异常类型1"""
pass
class SpecificCustomError2(CustomError):
"""特定的自定义异常类型2"""
pass
def some_function():
raise SpecificCustomError1("这是SpecificCustomError1的错误信息")
try:
some_function()
except SpecificCustomError1 as e:
print(f"捕获到SpecificCustomError1: {e}")
except SpecificCustomError2 as e:
print(f"捕获到SpecificCustomError2: {e}")
except CustomError as e:
print(f"捕获到CustomError: {e}")