title: Wrapping C++ dynamic array with Python+ctypes, segfault
body: <p>I wanted to wrap a small C++ code allocating an array with ctypes and there is something wrong with storing the address in a c_void_p object.</p>
  
  <p>(Note: the pointers are intentionally cast to <code>void*</code>, 'cause later I want to do the allocation the same way for arrays of C++ objects, too.)</p>
  
  <p>The C(++) functions to be wrapped:</p>
  
  <pre><code>void* test_alloc()
  {
      const int size = 100000000;
      int* ptr = new int[size];
      std::cout &lt;&lt; "Allocated " &lt;&lt; size * sizeof(int) &lt;&lt; " bytes @ " &lt;&lt;
                   ptr &lt;&lt; std::endl;
      return static_cast&lt;void*&gt;(ptr);
  }
  
  void test_dealloc(void* ptr)
  {
      int* iptr = static_cast&lt;int*&gt;(ptr);
      std::cout &lt;&lt; "Trying to free array @ " &lt;&lt; iptr &lt;&lt; std::endl;
      delete[] iptr;
  }
  </code></pre>
  
  <p>The Python wrapper (assume the former functions are already imported with ctypes):</p>
  
  <pre><code>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)
  </code></pre>
  
  <p>For small arrays (e.g. size = 10), it seems ok:</p>
  
  <pre><code>In [5]: t = TestAlloc()
  Allocated 40 bytes @ 0x1f20ef0
  self.pointer points to  0x1f20ef0
  
  In [6]: del t
  Trying to free array @ 0x1f20ef0
  </code></pre>
  
  <p>But if I want to allocate a large one (size = 100 000 000), problems occur:</p>
  
  <pre><code>In [2]: t = TestAlloc()
  Allocated 400000000 bytes @ 0x7faec3b71010 
  self.pointer points to  0xffffffffc3b71010L
  
  In [3]: del t
  Trying to free array @ 0xffffffffc3b71010
  Segmentation fault
  </code></pre>
  
  <p>The address stored in ctypes.c_void_p is obviously wrong, the upper 4 bytes are invalid.
  Somehow 32-bit and 64-bit addresses are mixed, and with the large array allocation the memory manager (in this case) is forced to return an address not representable on 32 bits (thx TonJ).</p>
  
  <p>Can someone please provide a workaround for this?</p>
  
  <p>The code has been compiled with g++ 4.4.3 and run on Ubuntu Linux 10.04 x86_64 with 4G RAM. Python version is 2.6.5.</p>
  
  <p>Thank you very much!</p>
  
  <p>UPDATE:</p>
  
  <p>I managed to solve the problem. I forgot to specify restype for <code>test_alloc()</code>. The default value for restype was <code>ctypes.c_int</code>, into which the 64-bit address did not fit. By also adding a <code>test_alloc.restype = ctypes.c_void_p</code> before the call of <code>test_alloc()</code> solved the problem.</p>