求python大牛帮看看ctypes.string_at的问题,,代码我也放在了gist上


代码我也放在了gist上 https://gist.github.com/hit9/7244344

foolib.c:

typedef struct post {    char *x;    char *y;    int x_z;} post_t;voidfoo (post_t *o, char *src){    int i=0;    char *p = src;    int len = strlen(src);    for (; *p != '\0'; i++, p++) {        if (*p == 'x') {            o->x = p;            o->x_z = len-i;        }    }    o->y=src;}

test.py:

from ctypes import *foolib = CDLL("./foolib.so")class Post(Structure):    _fields_ = (        ("x", c_void_p),        ("y", c_void_p),        ("x_z", c_int),    )o = Post()s = "iooxooiddfggggggggggggvd"foolib.foo(byref(o), create_string_buffer(s))print o.x_zprint string_at(o.x, o.x_z)print string_at(o.y, len(s))

其中,foolib.c用来生成一个动态链接库 foolib.so

打印结果为何是:

foo ➤ python test.py                                                                                                                   21ooiddfggggggggggggvdooiddfggggggggggggvd

而不是

21iooxooiddfggggggggggggvdooiddfggggggggggggvd

呢?

赞代码有可下载的 gist 版本!


我这边的结果和你的是不一样的。

>>> python2 test.pysrc: iooxooiddfggggggggggggvdx: xooiddfggggggggggggvd, y: iooxooiddfggggggggggggvd21dfggggggggggggvddfggggggggggggvd>>> python3 test.pysrc: iooxooiddfggggggggggggvdx: xooiddfggggggggggggvd, y: iooxooiddfggggggggggggvd21b'\x00\x00\x00\x00\x00\xc0+\x8d\xa2\xdf\x7f\x00\x00ggggggvd'b'\x00\x00\x00\x00\x00\x00\x00\x00\xc0+\x8d\xa2\xdf\x7f\x00\x00ggggggvd'

从 Python 3 的返回结果中,我们很容易看出来,部分内存被回收了。实际上 Python 2 版本在最后的 print 的值加上 repr 调用的话也很明显:

21'\x00\x00\x00\x00\x00dfggggggggggggvd''\x00\x00\x00\x00\x00\x00\x00\x00dfggggggggggggvd'

因为那些值都是 NUL,所以输出了也看不到而已。

于是,你知道啦,你创建的那个 string buffer 被回收掉了:

foolib.foo(byref(o), create_string_buffer(s))

这句改成这样子就好了:

buf = create_string_buffer(s)foolib.foo(byref(o), buf)

最终结果是这样子的:

src: iooxooiddfggggggggggggvdx: xooiddfggggggggggggvd, y: iooxooiddfggggggggggggvd21xooiddfggggggggggggvdiooxooiddfggggggggggggvd

因为o->x是野指针:create_string_buffer(s)返回的临时对象在foo调用结束以后就被回收了。

编橙之家文章,

评论关闭