C python扩展中的分段错误

时间:2019-07-14 21:31:32

标签: python c docker alpine python-extensions

我正在为python3.7编写一个C扩展模块。我有一个简单的结构,如PyObject:

typedef struct {
    PyObject_HEAD
    double attacker;
    double victim;
    double game_hardness;
    int inflation;
} RatingSystem;

和初始化程序:

static int 
RatingSystem_init(RatingSystem *self, PyObject *args, PyObject *kwargs) {
    double kek;
    static char *kwargs_list[] = {"attacker", "victim", "game_hardness", "inflation"};
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$dddi", kwargs_list,
                                      &self->attacker, &self->victim,
                                      &self->game_hardness, &self->inflation)) {
        return -1;
    }

    printf("Success\n");
    return 0;
}

如果我在python 3.7.3下的Mac OS上运行它,一切正常,但是如果我切换到alpine 3.10 python docker image(python:3.7-alpine),请执行以下初始化:

import rating_system
rs = rating_system.RatingSystem(attacker=1000.0, victim=1000.0, game_hardness=1300.0, inflation=1)

我得到Segmentation fault。在gdb下运行显示以下内容:

Program received signal SIGSEGV, Segmentation fault.
vgetargskeywords (args=0x7f87284f0050, kwargs=0x7f87284e0a00, format=<optimized out>, format@entry=0x7f8728301000 "|$dddi", kwlist=kwlist@entry=0x7f8728303020 <kwargs_list>, p_va=p_va@entry=0x7ffeeee6e4e0,
    flags=flags@entry=2) at Python/getargs.c:1640
1640    Python/getargs.c: No such file or directory.

如果我从初始化中删除inflation,代码也可以工作,即此代码:

static int 
RatingSystem_init(RatingSystem *self, PyObject *args, PyObject *kwargs) {
    static char *kwargs_list[] = {"attacker", "victim", "game_hardness"};
    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|$ddd", kwargs_list,
                                      &self->attacker, &self->victim,
                                      &self->game_hardness)) {
        return -1;
    }

    printf("Success\n");
    return 0;
}

工作。

初始化有什么问题吗?我尝试对最后一个参数使用不同的类型,但是没有运气。

1 个答案:

答案 0 :(得分:6)

根据PyArg_ParseTupleAndKeywords的{​​{3}},keywords参数期望以NULL结尾的关键字参数名称数组。

向您的NULL添加一个额外的kwargs_list元素:

static char *kwargs_list[] = {"attacker", "victim", "game_hardness", NULL};