[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