【问题标题】:Python ctypes 'segmentation fault: 11'Python ctypes'分段错误:11'
【发布时间】:2017-04-28 16:46:39
【问题描述】:

编辑: 在不改变 ulimit 的情况下爆炸的新示例,与 c 部分中的内容无关。

我是一名 python 用户(我从 edX 课程中学习),我一直在使用 ctypes 和 c(但我并不真正了解 c)。 当我使用一些特定参数(基本上是一个大数组大小)运行我的代码时,我的代码出现“分段错误:11”问题,这是一个复制我的代码所做的小例子:

test1.py:

import numpy as np
from numpy.ctypeslib import ndpointer
import ctypes as cy


Lib_Path = './lib.so'

class Simulacion:
    def __init__(self, ss,tm):
        self.tm    = tm;
        self.ss    = ss;

    def ejecutar(self):
        self.data   = np.empty((int(self.ss), self.tm), dtype = float)
        lib   = cy.CDLL(Lib_Path)
        dblc = cy.c_double; pntrc = ndpointer(dblc);  intc = cy.c_long
        lib.trisolve.argtypes = [intc, pntrc, intc]
        lib.trisolve(self.tm, self.data, self.ss)
        return self.data

ss = 10
tm  = int(1e6);

sim = Simulacion(ss,tm)
data = sim.ejecutar()

test1.c

void trisolve(int tm, double* data, int ss){

}

制作文件

SRC=test1
GCC=gcc-6
all:
    $(GCC) -fPIC -fopenmp -lm -c -O3 $(SRC).c
    $(GCC) -shared -lgomp -o lib.so $(SRC).o
clean:
    rm lib.so
    rm $(SRC).o

此代码在不更改 ulimit 的情况下爆炸。

对于我的真实代码,我使用的是“ulimit -s 65532”,这是我的 mac 中的最大堆栈大小。这限制了我正在使用的数组的大小,目前我需要复制它的大小。 对于我发现的问题,问题是数组存储在堆栈而不是堆中,因此由于 SO,我有这个硬限制。 所以我的问题是,如何将那个大数组传递给 C,将其存储在堆中,然后将其带回 python?

我主要使用python,而c部分的代码我在这个lenguaje中没有很好的格式,所以“堆栈”、“堆”和可能的“malloc”对我来说是新术语。

谢谢!

【问题讨论】:

  • "但我真的不知道 c" - 好吧,你应该去学习它。你正在尝试做一些比较高级的事情,但是你犯了一些基本的错误,比如混淆了 intlong,更不用说在 C 中使用 NumPy 数组的更复杂的部分了。
  • 我真的不需要比我已经知道的更多地学习它(除了我在这里问的)。因为我只使用 c 来解决矩阵(因为比 python 快得多),所以我可能可以对代码进行市长版并绕过我的问题,但我想知道如何像现在一样修复代码。谢谢。
  • “我只使用 c 来求解矩阵” - 什么,比如求解线性方程组? NumPy has that built in,它已经自动委托给 LAPACK。
  • 正如所写,这不是使用堆栈来存储数组。它在堆上分配,然后你迭代它。我也不明白为什么omp parallel for 会导致这个问题。但 CPython 本身至少需要 32K 的堆栈。
  • 比那更复杂,但是我不想在这里解释一切xD,在代码中我有一个很大的while,里面有几个for来设置条款矩阵,然后是它的解,然后对结果进行一些修改,然后再次迭代。 @eryksun 如果不使用堆栈,为什么当我使用ulimit -s 16 时,会出现分段错误,但如果我将其设置为例如 65532,代码可以正常工作吗? omp parallel for 不是这里的问题,程序甚至没有开始运行 c 代码。 (如果我把print放在那里,分段错误会发生在它之前)。

标签: python c ctypes heap-memory stack-memory


【解决方案1】:

终于找到了问题所在,和ctypes无关。 在我真正的 c 代码中,我用array[tm] 定义了一个数组,但tm 对于堆栈来说太大了。 为什么我能够用上面的代码复制问题?我真的不知道,但是当我今天尝试时(因为@eryksun 告诉他代码对他有用),它并没有爆炸。 谢谢您的帮助;以后我会努力学习更多的C语言。

【讨论】:

  • 如果您将该数组声明为自动变量,那么它确实使用堆栈。要使用堆,您需要malloc 内存,它返回一个void * 指针。在这种情况下,为了防止内存泄漏,您必须仔细控制函数的返回路径,以确保您 free 指针。
猜你喜欢
  • 1970-01-01
  • 2012-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-17
  • 1970-01-01
相关资源
最近更新 更多