我正在用C语言编写一个python扩展模块。当我在该模块的函数中声明大于4个元素的结构数组时,Python停止运行。

我正在编写模块以提高性能。
我已经声明了3个结构(“ SKU”,“ Cromosoma”,“ Aptitud”),我想创建一个Cromosoma数组,但是当我尝试创建包含4个以上元素的数组时,它就会中断。

// need_for_speed.c   extension module code
#include <Python.h>
#include <stdlib.h>
#define MAX_GENES_SIZE  2000
typedef struct{
    char codigo[30];
    double venta;
    char nombre[100];
    double categoria;
    double peso;
    double ubicacion_especifica;
    double ubicacion_actual;
    double ubicacion_a_mover;
    double stock;
} SKU;
typedef struct{
    double ubicaciones_rompe_regla;
    double cercania_medio;
    double desv_std_picks_x_seccion;
    double peso_x_ubicacion;
} Aptitud;
typedef struct{
    SKU genes[MAX_GENES_SIZE];
    Aptitud aptitud;
    int genes_size;
    int edad;
}Cromosoma;

static PyObject* prueba(PyObject* self, PyObject* args){
    Cromosoma a;
    SKU s;
    strcpy(s.codigo,"1212");
    a.genes[0] = s;
    Cromosoma poblacion[] = {a,a,a,a,a};
    printf("codigo %s ", poblacion[0].genes[0].codigo);
    return PyLong_FromDouble(1);
}
static PyMethodDef Methods[] = {
    {"prueba", prueba, METH_NOARGS, "Prueba general"},
    { NULL, NULL, 0, NULL }
};

// Module Definition struct
static struct PyModuleDef need_for_speed = {
    PyModuleDef_HEAD_INIT,
    "need_for_speed",
    "Modulo para aumento de la velocidad de procesamiento para el algoritmo genético",
    -1,
    Methods
};

// Initialize module
PyMODINIT_FUNC PyInit_need_for_speed(void)
{
    PyObject *m;
    m = PyModule_Create(&need_for_speed);
    return m;
}


setup.py来构建此模块:

from distutils.core import setup, Extension
setup(name = 'need_for_speed', version = '1.0',ext_modules = [Extension('need_for_speed', ['need_for_speed.c'])])


建立模块的命令:

python setup.py build


当我调用函数prueba时:

import need_for_speed
i = need_for_speed.prueba()


python会停止运行而不打印或不返回任何内容,但是如果在“ prueba”函数中将名为“ poblacion”的数组修改为只有4个元素,它将完美运行,返回1并打印“ codigo 1212”。

我正在使用Windows BTW。

最佳答案

可能是stack overflow

让我们看看您的结构假设它们仅占用单个成员的大小(忽略填充等)的大小:


SKU:7双打和130个字符-> 7 * 8字节+ 130字节-> 186字节
Aptitud:4倍-> 4 * 8字节-> 32字节
Cromosoma:2个整数,1个Aptitud和2000 SKU-> 2 * 4字节+ 32字节+ 2000 * 186字节-> 372040字节


因此,Chromosoma的一个实例将花费〜370kB。然后您创建其中的5/6;一个带有Cromosoma a;,一个用于数组中的每个插槽:4/5。

一个典型的堆栈只有几兆字节。使用6 * 370kB〜2.1MB,耗尽堆栈至少是合理的。例如,默认情况下,MSVC(Windows Visual Studio C / C ++编译器)仅使用1 MB。假设它无法使用大小为5的数组,但可以使用大小为4的数组,则看来您拥有约2 MB的堆栈。

为避免此问题,您可以增加堆栈大小(具体取决于编译器)。但是,当您需要更多的Chromosoma或更改SKU的数量时,增加堆栈大小将再次导致问题。

另一种选择(可能比增加堆栈大小更好)是在堆上分配所有大数组。例如,您可以在堆上分配poblacion-和/或使Chromosoma.genes成为指向SKU数组的指针。

09-04 17:52
查看更多