2010-06-23 78 views
4

我想包装一个小的C++代码分配与ctypes的阵列,并且有一些错误在一个c_void_p对象存储地址。包装C++动态数组与Python + ctypes的,段错误

(注意:该指针被故意投给void*,“以后导致我想要做的分配的C++对象阵列相同的方式,太)

的C(++),以被包裹的功能:

void* test_alloc() 
{ 
    const int size = 100000000; 
    int* ptr = new int[size]; 
    std::cout << "Allocated " << size * sizeof(int) << " bytes @ " << 
       ptr << std::endl; 
    return static_cast<void*>(ptr); 
} 

void test_dealloc(void* ptr) 
{ 
    int* iptr = static_cast<int*>(ptr); 
    std::cout << "Trying to free array @ " << iptr << std::endl; 
    delete[] iptr; 
} 

Python的包装物(假设前者功能已经与ctypes的进口):

class TestAlloc(object): 
    def __init__(self): 
     self.pointer = ctypes.c_void_p(test_alloc()) 
     print "self.pointer points to ", hex(self.pointer.value) 

    def __del__(self): 
     test_dealloc(self.pointer) 

对于小阵列(例如,大小= 10),它似乎确定:

In [5]: t = TestAlloc() 
Allocated 40 bytes @ 0x1f20ef0 
self.pointer points to 0x1f20ef0 

In [6]: del t 
Trying to free array @ 0x1f20ef0 

但是,如果我想分配一个大一个(大小= 100 000 000),会出现问题:

In [2]: t = TestAlloc() 
Allocated 400000000 bytes @ 0x7faec3b71010 
self.pointer points to 0xffffffffc3b71010L 

In [3]: del t 
Trying to free array @ 0xffffffffc3b71010 
Segmentation fault 

存储在ctypes.c_void_p地址显然是错误的,高4个字节无效。 不知何故32位和64位地址是混合的,并且在大数组分配的情况下,内存管理器(在这种情况下)被迫返回一个32位(thx TonJ)不可表示的地址。

是否有人可以提供这样的解决方法吗?

的代码被编译以克++ 4.4.3和在Ubuntu Linux 10.04 x86_64的与4G RAM中运行。 Python版本是2.6.5。

非常感谢!

更新:

我设法解决了这个问题。我忘记了为test_alloc()指定restype。 restype的默认值是ctypes.c_int,64位地址不适合。在test_alloc()的呼叫之前还通过添加test_alloc.restype = ctypes.c_void_p解决了该问题。

回答

1

从只盯着它,它看来问题不在小/大数组分配,但在32位和64位地址的组合。 在你的例子中,小阵列的地址适合32位,但大阵列的地址不适用。

+0

是的,正确制定。幸运的是,在大数组大小的情况下,内存管理器不得不将其分配到不再适合32位的地址,因此该错误变得明显。 – cornail 2010-06-23 10:34:24