[C++-sig] boost/python 1.33.1 breaks aliasing rules (original) (raw)

David Abrahams dave at boost-consulting.com
Thu Dec 8 21:52:45 CET 2005


Philipp Thomas <pth at suse.de> writes:

* David Abrahams (dave at boost-consulting.com) [20051208 07:06]:

Which, AFAICT, means that our casts aren't hurting anybody, regardless of whether we use -fno-strict-aliasing. Right? Right. Do you have an idea how to pass -fno-strict-aliasing only when build libboostpython?

Yes; we can put it in the Jamfile.

where the union performs, essentially, a reinterpret cast of a PyObject*& to a PyTypeObject*&, which could be a completely different thing. Please? I'm still passing a PyObject*, as the union is essentially a reinterpretcast<PyObject *>(PyTypeObject *).

No. A reinterpret_cast is not required to simply interpret the same bits differently, as the union trick does. Aside from certain round-trip conversion guarantees, its effects are completely implementation-defined. To put it differently, what you're doing there is equivalent to:

PyTypeObject* s = &PyString_Type; *reinterpret_cast<PyObject**>(&s)

which is another thing altogether.

Boost.Python is doing ((PyObject*)&PyString_Type) and passes the result to Python. That is not yet undefined behavior. If Python internally casts that back to PyTypeObject*, it's free to use the pointer as it likes without undefined behavior. If I treat Python as a black box, I can assume it does something like that, since Python documents that we can pass such punned pointers. Instead Python uses -fno-strict-aliasing, exploiting a compiler-specific feature to avoid undefined behavior, but it's the same thing from my POV. So right now Boost.Python isn't doing anything unspecified or nonportable.

However, the reinterpretation of bits as you are doing does introduce unspecified behavior at least, by 5.2.10, para 7:

7 A pointer to an object can be explicitly converted to a pointer to an object of different type. 65) Except that converting an rvalue of type pointer to T1'' to the type pointer to T2'' (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value, the result of such a pointer conversion is unspecified.

I would strongly oppose the former, There's no disagreement as I hate #ifdef because it always makes code nearly unreadable.

but the latter might be no worse (and may be a little better) than leaving the C-style casts in there. Hmm, I'll try to come up with a way to encapsulate it in macros.

Forget the macros; we can do it with functions. See boost/python/cast.hpp.

-- Dave Abrahams Boost Consulting www.boost-consulting.com



More information about the Cplusplus-sig mailing list