简体   繁体   English

使用ctypes和线程时出现分段错误

[英]Segmentation fault when using ctypes and threading

I wrote a Python wrapper for a C library using ctypes . 我使用ctypes为C库编写了Python包装器。 Everything worked fine, until I tried it with the threading module. 一切工作正常,直到我使用threading模块对其进行了尝试。

Here is a small example to reproduce it: 这是一个重现它的小例子:

foo.c foo.c的

#include <stdlib.h>
#include <assert.h>

char *foo_init() {
    char *result = (char*)malloc(sizeof(char));
    assert(result);
    return result;
}

char foo_get(const char* p) {
    return *p;
}

void foo_set(char *p, char value) {
    *p = value;
}

void foo_del(char *p) {
    free(p);
}

foo.py foo.py

import threading
import ctypes
libfoo=ctypes.CDLL('foo.so')

libfoo.foo_init.restype = ctypes.c_void_p
libfoo.foo_get.restype = ctypes.c_char

class Foo:
    def __init__(self):
        self.__obj__ = libfoo.foo_init()

    def get(self):
        return libfoo.foo_get(self.__obj__)

    def set(self, value):
        libfoo.foo_set(self.__obj__, ctypes.c_char(value))

    def __del__(self):
        libfoo.foo_del(self.__obj__)

x = Foo()
x.set(b'x')
print(x.get())

def compute():
    y = Foo()
    y.set(b'y')
    print(y.get())

t = threading.Thread(target=compute)
t.start()
t.join()

Compilation: 汇编:

gcc -Wall -shared -o foo.so -fPIC foo.c

Execution: 执行:

export LD_LIBRARY_PATH=.
python3 foo.py

Result: 结果:

b'x'
[1]    8627 segmentation fault  python3 foo.py

We see here that x.get() is correctly printed whereas y.get() does a segmentation fault. 我们在这里看到x.get()正确打印,而y.get()则出现分段错误。 Thus, it seems that there is a problem linked to ctypes and threading . 因此,似乎存在与ctypesthreading相关的问题。

Note that if I move the initialization of y outside of the compute function, then the program exits normally. 请注意,如果将y的初始化移至compute函数之外,则程序将正常退出。

Moreover, each of the functions which manipulate the pointer produce a segmentation fault (eg if I just keep the __init__ and __del__ functions, there is still a crash). 而且,操纵指针的每个函数都会产生分段错误(例如,如果我只保留__init____del__函数,则仍然会发生崩溃)。

Any idea on how to fix this? 关于如何解决此问题的任何想法?

@user2357112 gave me the answer in comments: adding the (good) return type and the arguments types is important. @ user2357112在注释中给了我答案:添加(good)返回类型和参数类型很重要。

Replacing the beginning of foo.py by the following fix the problem: 通过以下替换foo.py的开头foo.py此问题:

libfoo.foo_init.restype = ctypes.POINTER(ctypes.c_char)
libfoo.foo_init.argtypes = []
libfoo.foo_get.restype = ctypes.c_char
libfoo.foo_get.argtypes = [ctypes.POINTER(ctypes.c_char)]
libfoo.foo_set.argtypes = [ctypes.POINTER(ctypes.c_char), ctypes.c_char]
libfoo.foo_del.argtypes = [ctypes.POINTER(ctypes.c_char)]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM