Я разрабатываю расширения C из рекламы Python, я получаю некоторый segfaults (неизбежный во время разработки...).
Я ищу способ отобразиться, в которой строке кода segfault происходит (идея похожа на трассировку каждой строки кода), как я могу сделать это?
Вот способ вывести имя файла и номер строки каждой строки Python, выполняемой вашим кодом:
import sys
def trace(frame, event, arg):
print "%s, %s:%d" % (event, frame.f_code.co_filename, frame.f_lineno)
return trace
def test():
print "Line 8"
print "Line 9"
sys.settrace(trace)
test()
Вывод:
call, test.py:7
line, test.py:8
Line 8
line, test.py:9
Line 9
return, test.py:9
(Вы, вероятно, захотите записать вывод трассировки в файл, конечно.)
Если вы работаете в Linux, запустите python под gdb
gdb python
(gdb) run /path/to/script.py
## wait for segfault ##
(gdb) backtrace
## stack trace of the c code
Сбои в работе расширений C очень часто являются результатом отсутствия увеличения счетчика ссылок при создании новой ссылки на объект. Это делает их очень трудными для отслеживания, поскольку segfault возникает только после удаления последней ссылки из объекта, и даже тогда часто только тогда, когда выделяется какой-либо другой объект.
Вы не говорите, сколько кода расширения C вы написали до сих пор, но если вы только начинаете, подумайте, можете ли вы использовать ctypes или Cython . Ctypes может быть недостаточно гибким для ваших нужд, но вы должны иметь возможность ссылаться практически на любую библиотеку C с помощью Cython и автоматически поддерживать все счетчики ссылок.
Этого не всегда достаточно: если ваши объекты Python и любые базовые объекты C имеют разное время жизни, вы все равно можете столкнуться с проблемами, но это значительно упрощает ситуацию.