帮助我理解为什么我对Python';s ctypes模块出现故障

帮助我理解为什么我对Python';s ctypes模块出现故障,python,malloc,ctypes,Python,Malloc,Ctypes,我试图理解Python的“ctypes”模块。我总结了一个简单的示例,理想情况下,它包装了statvfs()函数调用。代码如下所示: from ctypes import * class struct_statvfs (Structure): _fields_ = [ ('f_bsize', c_ulong), ('f_frsize', c_ulong), ('f_blocks', c_ulong),

我试图理解Python的“ctypes”模块。我总结了一个简单的示例,理想情况下,它包装了statvfs()函数调用。代码如下所示:

from ctypes import *

class struct_statvfs (Structure):
    _fields_ = [
            ('f_bsize', c_ulong),
            ('f_frsize', c_ulong),
            ('f_blocks', c_ulong),
            ('f_bfree', c_ulong),
            ('f_bavail', c_ulong),
            ('f_files', c_ulong),
            ('f_ffree', c_ulong),
            ('f_favail', c_ulong),
            ('f_fsid', c_ulong),
            ('f_flag', c_ulong),
            ('f_namemax', c_ulong),
            ]


libc = CDLL('libc.so.6')
libc.statvfs.argtypes = [c_char_p, POINTER(struct_statvfs)]
s = struct_statvfs()

res = libc.statvfs('/etc', byref(s))
print 'return = %d, f_bsize = %d, f_blocks = %d, f_bfree = %d' % (
    res, s.f_bsize, s.f_blocks, s.f_bfree)
运行此命令将始终返回:

return = 0, f_bsize = 4096, f_blocks = 10079070, f_bfree = 5048834
*** glibc detected *** python: free(): invalid next size (fast): 0x0000000001e51780 ***
*** glibc detected *** python: malloc(): memory corruption (fast): 0x0000000001e517e0 ***
我还没有找到任何使用复杂类型作为参数调用函数的例子(有很多函数返回复杂类型的例子),但是在看了一天左右的ctypes文档之后,我认为我的调用语法是正确的……实际上它调用的是statvfs()打电话并返回正确的结果

我是不是误解了ctypes文档?还是这里发生了什么事


谢谢

statvfs的手册页声明它使用的结构“定义大致如下”,因此您不一定认为手册页的字段列表是完整的

我的猜测是,在您定义的结构结束之后,还有其他结构字段。这会导致statvfs函数覆盖结构外部的内存。通过在我的结构定义中的
\u字段中添加一个巨大的填充字段,我解决了这个问题:

("padding", c_int * 1000),

请记住,我的剧本与你的剧本表达问题的方式不同;我得到了一个segfault,而你只得到了一些错误消息。尽管如此,我还是猜测这是同一个问题,因此您应该尝试添加一些填充,看看问题是否仍然存在。

正如Eli所指出的,在/usr/include/bits/statvfs.h中,您的结构定义不正确

在我的64位Gentoo系统上,它将是:

 class struct_statvfs (Structure):
    _fields_ = [
            ('f_bsize', c_ulong),
            ('f_frsize', c_ulong),
            ('f_blocks', c_ulong),
            ('f_bfree', c_ulong),
            ('f_bavail', c_ulong),
            ('f_files', c_ulong),
            ('f_ffree', c_ulong),
            ('f_favail', c_ulong),
            ('f_fsid', c_ulong),
            ('f_flag', c_ulong),
            ('f_namemax', c_ulong),
            ('__f_space', c_int * 6) # you are missing this
            ]

根据成功的
pyfuse
ctypes-wrappers for-Fuse,以下内容用于Linux上的
struct-statvfs

class c_statvfs(Structure):
    _fields_ = [
        ('f_bsize', c_ulong),
        ('f_frsize', c_ulong),
        ('f_blocks', c_fsblkcnt_t),
        ('f_bfree', c_fsblkcnt_t),
        ('f_bavail', c_fsblkcnt_t),
        ('f_files', c_fsfilcnt_t),
        ('f_ffree', c_fsfilcnt_t),
        ('f_favail', c_fsfilcnt_t)]

更多信息:

执行此命令以获得系统上的
struct statvfs
的确切定义:

echo '#include <sys/statvfs.h>' | gcc -E - | less
echo'#include'| gcc-E-| less
然后按
/struct statvfs
跳到定义并从此处浏览


再看看fusepy,还有。

我还没有找到答案,但我可以告诉你,当我将代码作为脚本运行时,它对我来说运行良好,但当我在交互式解释器中运行它时,它会导致segfault。具体来说,它会在看似随机的一段时间后,或在解释器退出时(以先到者为准)导致segfault。我会继续尝试解决这个问题,但我认为这些信息可能会让比我更了解这个问题的人了解到一些情况。一个问题可能是您不必正确定义类结构,例如,您的类结构比libc认为的更小。运行这个小C程序来验证:#include int main(){return!printf(“%d\n”,sizeof(struct statvfs));}错误和过时的文档比没有文档更糟糕。我没有想到一个困扰我的结构(与statvfs无关)的定义。幸好我看到了这个问题。c_int*6似乎足够了(但*1000更安全,*100应该足够安全),请参阅Linux上的/usr/include/bits/statvfs.h:struct statvfs包含int_f_spare[6];可能想看一看我提交的fusepy补丁,其中包含对其STATVs的更正。啊,很好。我不知道它已经过时了。顺便说一句,我注意到fusepy只有一个STATF的钩子,而不是STATVF。这就是我信任手册页的原因。谢谢你的建议!因为这是我第一次使用ctypes,所以我不确定故障模式到底意味着什么。获取结构定义的好捷径。我必须记住这一点。是的,ctypes被谈论了很多,但要正确定义所有的东西仍然是痛苦的。C编译器是必要的,这真的没有帮助。应该有一个官方的ABI标准,C和其他语言可以相互依赖。