[C++-sig] GC error due to stl_input_iterator
Wichert Akkerman
wichert at wiggy.net
Wed Feb 6 14:30:49 CET 2013
I am running into some unexpected errors when using stl_input_iterator. I have a fairly simple converter registered to convert an iterable list of values (custom enum) to a unordered_set. The code looks like this:
struct advicetype_set_from_python {
advicetype_set_from_python() {
converter::registry::push_back(&convertible, &construct, type_id<std::unordered_set<AdviceType>>());
}
static void* convertible(PyObject *obj) {
if (obj==Py_None)
return obj;
PyObject* iter = PyObject_GetIter(obj);
if (iter==NULL) {
throw_error_already_set();
return 0;
}
Py_DECREF(iter);
return obj;
}
static void construct(PyObject* obj, converter::rvalue_from_python_stage1_data *data) {
std::unordered_set<AdviceType> result;
if (obj!=Py_None) {
object o = object(handle<>(obj));
stl_input_iterator<AdviceType> begin(o), end;
result.insert(begin, end);
}
void *storage = ((converter::rvalue_from_python_storage<std::unordered_set<AdviceType>>*)data)->storage.bytes;
new (storage) std::unordered_set<AdviceType>(result);
data->convertible = storage;
}
};
When using this code we were seeing segfaults due to what appears to be invalid reference counters. Since I suspected a problem in this convertor I wrote a simple test which triggers the converter a number of times:
for i in range(5000):
my_func({AdviceType.one, AdviceType.two})
Which had an interesting result: the tests immediately aborted with a "Fatal Python error: GC object already tracked" error. Commenting out the contents of the if-statement in construct() made the problem go away, which makes we think the bug is in the stl_input_iterator used there. Am I doing something wrong here, or is this a boost bug? FWIW I am seeing this under both Boost 1.48 on an Ubuntu 12.04 machine and Boost 1.52 on OSX 10.8.
I am not sure if this is related, but clang outputs an interesting warning for the in-place new that is required here:
warning: cast from 'converter::rvalue_from_python_stage1_data *' to 'converter::rvalue_from_python_storage<std::unordered_set<AdviceType> > *' increases required alignment
from 8 to 16 [-Wcast-align]
void *storage = ((converter::rvalue_from_python_storage<std::unordered_set<AdviceType>>*)data)->storage.bytes;
Wichert.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.python.org/pipermail/cplusplus-sig/attachments/20130206/4e43ed81/attachment.html>
More information about the Cplusplus-sig
mailing list