[C++-sig] Calling list.__len__() from C++ causes crash with >= 100 elements

Geoffrey French gsculpt at googlemail.com
Sat Aug 5 11:57:05 CEST 2006


Hi,

I am currently running Python 2.4.3 and Boost 1.33.1-5 on Fedora Core 5.
I have prepared some test code which seems to cause a seg fault when
C++ code attempts to get the length of a list which has 100 or more
elements.
Valgrind seems to report it as an attempt to dereference a NULL pointer.
An application that I have written (http://gsculpt.sf.net) displays the same
behavior when compiled for Fedora Core 5, and Windows.

Here is the code for a C++ module to demonstrate this:


======================== boostpythonbug.cpp ========================
#include <iostream>

#include <boost/python.hpp>
using namespace boost::python;



void printListLength(boost::python::object elements)
{
    boost::python::extract<int> lenExtract( elements.attr( "__len__" )() );
    if ( lenExtract.check() )
    {
        int numElements = lenExtract;
        std::cout << numElements << " elements" << std::endl;
    }
}

void printValue(boost::python::object obj)
{
    boost::python::extract<int> vExtract( obj.attr( "value" )() );
    if ( vExtract.check() )
    {
        int v = vExtract;
        std::cout << "value = " << v << std::endl;
    }
}

BOOST_PYTHON_MODULE(ListLength)
{
    def( "printListLength", &printListLength );
    def( "printValue", &printValue );
}
======================== boostpythonbug.cpp ========================

To compile:
$ c++ boostpythonbug.cpp --shared -o ListLength.so
-lpython2.4-lboost_python -I/usr/include/python2.4



The python module below tests this module:

======================== boostpythonbug.py ========================
from ListLength import *

class Test (object):
    def __init__(self, x):
        self.x = x

    def value(self):
        return self.x

    def __len__(self):
        return self.x



printValue( Test( 5 ) )
printValue( Test( 99 ) )
printValue( Test( 100 ) )
printValue( Test( 101 ) )

printListLength( Test( 5 ) )
printListLength( Test( 99 ) )
printListLength( Test( 100 ) )
printListLength( Test( 101 ) )

printListLength( [] )
printListLength( [ 0 ] )
printListLength( range( 0, 5 ) )
printListLength( range( 0, 99 ) )
printListLength( range( 0, 100 ) )
======================== boostpythonbug.py ========================


Here is the output:

$ python boostpythonbug.py
value = 5
value = 99
value = 100
value = 101
5 elements
99 elements
100 elements
101 elements
0 elements
1 elements
5 elements
99 elements
Segmentation fault (core dumped)



Getting integer values from a generic function call works fine,
as demonstrated by printValue(), and printListLength() invoked
on a 'Test' object.
It only seems to affect lists.

Defining printListLength as:
void printListLength(boost::python::object elements)
OR
void printListLength(boost::python::list elements)
does not prevent the seg-faulting.
The second definition means you can only pass lists though,
i.e. the cases where a 'Test' object is passed will not work.


Is this a boost::python bug, or have I screwed up some how?
Thank you for your time.



Regards

Geoffrey French
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20060805/1ddab512/attachment.htm>


More information about the Cplusplus-sig mailing list