python - ctypes.string_at的莫名奇妙的问题
伊谢尔伦
伊谢尔伦 2017-04-17 11:45:46
[Python讨论组]

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

foolib.c:

typedef struct post {
    char *x;
    char *y;
    int x_z;
} post_t;


void
foo (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_z

print string_at(o.x, o.x_z)
print string_at(o.y, len(s))

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

打印结果为何是:

foo ➤ python test.py                                                                                                                   
21
ooiddfggggggggggggvd
ooiddfggggggggggggvd

而不是

21
iooxooiddfggggggggggggvd
ooiddfggggggggggggvd

呢?

伊谢尔伦
伊谢尔伦

小伙看你根骨奇佳,潜力无限,来学PHP伐。

全部回复(2)
高洛峰

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


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

>>> python2 test.py
src: iooxooiddfggggggggggggvd
x: xooiddfggggggggggggvd, y: iooxooiddfggggggggggggvd
21
dfggggggggggggvd
dfggggggggggggvd
>>> python3 test.py
src: iooxooiddfggggggggggggvd
x: xooiddfggggggggggggvd, y: iooxooiddfggggggggggggvd
21
b'\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: iooxooiddfggggggggggggvd
x: xooiddfggggggggggggvd, y: iooxooiddfggggggggggggvd
21
xooiddfggggggggggggvd
iooxooiddfggggggggggggvd
PHP中文网

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

热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板
关于我们 免责申明 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送
PHP中文网APP
随时随地碎片化学习
PHP中文网抖音号
发现有趣的

Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号