我编写了这个C 扩展模块,它使用快速矩阵乘法计算斐波那契数。
#include <Python.h>
struct Matrix {
PyObject *m[2][2];
};
static struct Matrix matrix_mult(struct Matrix mat1, const struct Matrix mat2)
{
struct Matrix matrix;
PyObject *mults[8];
for (int i = 0; i < 8; i++) {
mults[i] = PyNumber_Multiply(mat1.m[i/4][i%2], mat2.m[i%2][(i/2)&1]);
}
for (int i = 0; i < 4; i++) {
matrix.m[i/2][i%2] = PyNumber_Add(mults[2*i], mults[2*i+1]);
}
for (int i = 0; i < 8; i++) {
Py_DECREF(mults[i]);
}
return matrix;
}
static void matrix_free(struct Matrix *matrix)
{
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
Py_DECREF(matrix->m[i][j]);
}
}
}
static struct Matrix matrix_pow(struct Matrix matrix, int n)
{
struct Matrix result = {{
{PyLong_FromLong(1L), PyLong_FromLong(0L)},
{PyLong_FromLong(0L), PyLong_FromLong(1L)}
}};
struct Matrix result_old;
struct Matrix matrix_old;
while (n > 0) {
if (n % 2 == 0) {
n /= 2;
matrix_old = matrix;
matrix = matrix_mult(matrix_old, matrix_old);
matrix_free(&matrix_old);
} else {
//n--;
n /= 2;
result_old = result;
matrix_old = matrix;
result = matrix_mult(result_old, matrix);
matrix = matrix_mult(matrix_old, matrix_old);
matrix_free(&result_old);
matrix_free(&matrix_old);
}
}
return result;
}
static PyObject *fib_mat(PyObject *self, PyObject *args)
{
long long int n;
if(!PyArg_ParseTuple(args, "L", &n))
return NULL;
struct Matrix fib_matrix = {{
{PyLong_FromLong(0L), PyLong_FromLong(1L)},
{PyLong_FromLong(1L), PyLong_FromLong(1L)}
}};
struct Matrix result = matrix_pow(fib_matrix, n + 1);
PyObject *inswer = result.m[0][0];
Py_INCREF(inswer);
matrix_free(&result);
matrix_free(&fib_matrix);
return inswer;
}
static PyMethodDef func_table[] = {
{ "fib_mat", fib_mat, METH_VARARGS, "Calculates fib number" },
{ NULL, NULL, 0, NULL }
};
static struct PyModuleDef fib_module = {
PyModuleDef_HEAD_INIT,
"fib_module",
"fibonacci Module",
-1,
func_table
};
PyMODINIT_FUNC PyInit_fib_module(void)
{
return PyModule_Create(&fib_module);
}
问题是当我使用该模块运行以下 Python 3 代码时:
import fib_module
i = 0
while i < 10:
fib_module.fib_mat(i)
i += 1
它返回下面列出的错误:
free():无效指针已中止(核心转储)
它似乎是由 C 扩展模块内部的某些东西引起的,但没有显式free
调用。