Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x cython和python3枚举的奇怪行为_Python 3.x_Python 2.7_Cython_Enumerate - Fatal编程技术网

Python 3.x cython和python3枚举的奇怪行为

Python 3.x cython和python3枚举的奇怪行为,python-3.x,python-2.7,cython,enumerate,Python 3.x,Python 2.7,Cython,Enumerate,我们在python3中有一大堆要移植的代码,我们在enumerate中面临着一种非常奇怪的行为 cdef char **c_argv c_argv = <char**>malloc(sizeof(char*) * len(args)) for idx, s in enumerate(args): if bytes != str: s = s.encode('utf-8') c_argv[idx] = s 这也不行 以下是我们测试的完整副本: 测试枚举

我们在python3中有一大堆要移植的代码,我们在enumerate中面临着一种非常奇怪的行为

cdef char **c_argv
c_argv = <char**>malloc(sizeof(char*) * len(args))
for idx, s in enumerate(args):
    if bytes != str:
        s = s.encode('utf-8')
    c_argv[idx] = s
这也不行

以下是我们测试的完整副本:

测试枚举.pyx

from libc.stdlib cimport malloc, free
from libc.string cimport const_char

def test_enumerate(args):
    cdef char **c_argv
    c_argv = <char**>malloc(sizeof(char*) * len(args))
    for idx, s in enumerate(args):
        if bytes != str:
            s = s.encode('utf-8')
        c_argv[idx] = s

    for i in range(len(args)):
        print("Set by enumerate",c_argv[i])        
    free(c_argv)

def test_loop_obj(args):
    cdef char **c_argv
    c_argv = <char**>malloc(sizeof(char*) * len(args))
    idx=0
    for s in (args):
        if bytes != str:
            s = s.encode('utf-8')
        c_argv[idx] = s
        idx = idx+1
        
    for i in range(len(args)):
        print("Set by loop on objects",c_argv[i])        
    free(c_argv)

def test_loop(args):
    cdef char **c_argv
    c_argv = <char**>malloc(sizeof(char*) * len(args))
    for i in range(len(args)):
        if bytes != str:
            args[i] = args[i].encode('utf-8')
        c_argv[i] = args[i]

    for i in range(len(args)):
        print("Set by loop on index",c_argv[i])        
    free(c_argv)
setup.py:

from setuptools import setup
from Cython.Build import cythonize
setup(
    ext_modules = cythonize("test_enumerate.pyx")
)
我们通过以下方式进行编译:

python/python3 setup.py build_ext --inplace
下面的输出说明了我们的问题:

$ python test.py
('Set by enumerate', 'salut')
('Set by enumerate', 'tu')
('Set by enumerate', 'vas')
('Set by enumerate', 'bien')
('Set by loop on objects', 'salut')
('Set by loop on objects', 'tu')
('Set by loop on objects', 'vas')
('Set by loop on objects', 'bien')
('Set by loop on index', 'salut')
('Set by loop on index', 'tu')
('Set by loop on index', 'vas')
('Set by loop on index', 'bien')
有人能解释我们在这里遗漏了什么吗

c_argv[idx] = s
这将
c_argv[idx]
设置为指向
s
数据的指针。指针仅在
s
仍然存在时有效

s = s.encode('utf-8')
如果发生此行,则会创建一个新的编码的
s
,导致先前编码的
s
减少,因此可能会被释放

基本上,除非您了解(并且能够控制)c指针的生命周期,否则不要乱动它们

$ python3 test.py
('Set by enumerate', b'bien')
('Set by enumerate', b'bien')
('Set by enumerate', b'bien')
('Set by enumerate', b'bien')
('Set by loop on objects', b'bien')
('Set by loop on objects', b'bien')
('Set by loop on objects', b'bien')
('Set by loop on objects', b'bien')
('Set by loop on index', b'salut')
('Set by loop on index', b'tu')
('Set by loop on index', b'vas')
('Set by loop on index', b'bien')
c_argv[idx] = s
s = s.encode('utf-8')