[C++-sig] return_internal_reference and implicitly_convertible danger

Raoul Gough RaoulGough at yahoo.co.uk
Tue Sep 16 18:16:48 CEST 2003


Not sure if it's worth looking into this in any depth, but I've
discovered that implicitly_convertible and return_internal_reference
can combine in a nasty way. If I have a function exposed to Python
like this:

IntWrapper const *bar (IntWrapper const &i) {
  return &i;
}

// ...
  implicitly_convertible<int, IntWrapper> ();

  def ("bar", bar, return_internal_reference<>());

then calling bar(IntWrapper(3)) is OK, but bar(3) returns a dangling
reference:

>>> print bar(IntWrapper(3))
3
>>> print bar(3)
1243312

I suspect there is a problem because the implicit conversion is
happening in C++, and that object gets destroyed prematurely (maybe
because the Python function call infrastructure doesn't have a
reference to it).

BTW, I'm not claiming that this client code should work! Then again,
maybe there's an easy way to catch this in the library that I don't
know about. Actual test code follows for completeness.

#include <boost/python/def.hpp>
#include <boost/python/class.hpp>
#include <boost/python/module.hpp>
#include <boost/python/implicit.hpp>
#include <sstream>
#include <string>

struct IntWrapper {
  int mI;

  IntWrapper (int i) : mI (i) { }

  std::string repr () const {
    std::stringstream temp;
    temp << mI;
    return temp.str();
  }
};

IntWrapper const *bar (IntWrapper const &i) {
  return &i;
}

BOOST_PYTHON_MODULE (testint) {
  using namespace boost::python;

  implicitly_convertible<int, IntWrapper> ();

  class_<IntWrapper> ("IntWrapper", init<int>())
    .def ("__repr__", &IntWrapper::repr);

  def ("bar", bar, return_internal_reference<>());
}

-- 
Raoul Gough.
(setq dabbrev-case-fold-search nil)





More information about the Cplusplus-sig mailing list