1

我编写了这个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调用。

4

0 回答 0