[Cython] [cython-users] C++: how to handle failures of 'new'?

mark florisson markflorisson88 at gmail.com
Sun Jul 8 11:34:47 CEST 2012


On 8 July 2012 08:59, Robert Bradshaw <robertwb at gmail.com> wrote:
> On Fri, Jul 6, 2012 at 2:33 AM, mark florisson
> <markflorisson88 at gmail.com> wrote:
>> On 6 July 2012 03:34, Dag Sverre Seljebotn <d.s.seljebotn at astro.uio.no> wrote:
>>>
>>>
>>> mark florisson <markflorisson88 at gmail.com> wrote:
>>>
>>>>On 5 July 2012 21:46, Dag Sverre Seljebotn <d.s.seljebotn at astro.uio.no>
>>>>wrote:
>>>>>
>>>>>
>>>>> mark florisson <markflorisson88 at gmail.com> wrote:
>>>>>
>>>>>>On 3 July 2012 20:15, Robert Bradshaw <robertwb at gmail.com> wrote:
>>>>>>> On Tue, Jul 3, 2012 at 11:43 AM, Dag Sverre Seljebotn
>>>>>>> <d.s.seljebotn at astro.uio.no> wrote:
>>>>>>>> On 07/03/2012 08:23 PM, Robert Bradshaw wrote:
>>>>>>>>>
>>>>>>>>> On Tue, Jul 3, 2012 at 11:11 AM, Stefan
>>>>Behnel<stefan_ml at behnel.de>
>>>>>>>>> wrote:
>>>>>>>>>>
>>>>>>>>>> Robert Bradshaw, 03.07.2012 19:58:
>>>>>>>>>>>
>>>>>>>>>>> On Tue, Jul 3, 2012 at 9:38 AM, Stefan Behnel wrote:
>>>>>>>>>>>>
>>>>>>>>>>>> Dag Sverre Seljebotn, 03.07.2012 18:11:
>>>>>>>>>>>>>
>>>>>>>>>>>>> On 07/03/2012 09:14 AM, Stefan Behnel wrote:
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> I don't know what happens if a C++ exception is not being
>>>>>>caught, but
>>>>>>>>>>>>>> I
>>>>>>>>>>>>>> guess it would simply crash the application. That's a bit
>>>>more
>>>>>>>>>>>>>> visible than
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Yep.
>>>>>>>>>>>>>
>>>>>>>>>>>>>> just printing a warning when a Python exception is being
>>>>>>ignored due
>>>>>>>>>>>>>> to a
>>>>>>>>>>>>>> missing declaration. It's really unfortunate that our
>>>>>>documentation
>>>>>>>>>>>>>> didn't
>>>>>>>>>>>>>> even mention the need for this, because it's not immediately
>>>>>>obvious
>>>>>>>>>>>>>> that
>>>>>>>>>>>>>> Cython won't handle errors in "new", and testing for memory
>>>>>>errors
>>>>>>>>>>>>>> isn't
>>>>>>>>>>>>>> quite what people commonly do in their test suites.
>>>>>>>>>>>>>>
>>>>>>>>>>>>>> Apart from that, I agree, users have to take care to
>>>>properly
>>>>>>declare
>>>>>>>>>>>>>> the
>>>>>>>>>>>>>> API they are using.
>>>>>>>>>>>>>
>>>>>>>>>>>>>
>>>>>>>>>>>>> Is there any time you do NOT want a "catch (...) {}" block? I
>>>>>>can't
>>>>>>>>>>>>> see a
>>>>>>>>>>>>> C++ exception propagating to Python-land doing anything
>>>>useful
>>>>>>ever.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> That would have been my intuition, too.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> If it's actually embedded, with the main driver in C++, one
>>>>might
>>>>>>want
>>>>>>>>>>> it to propagate up.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>> But what kind of a propagation would that be? On the way out, it
>>>>>>could
>>>>>>>>>> induce anything, from side effects to resource leaks to crashes,
>>>>>>>>>> depending
>>>>>>>>>> on what the state of the surrounding code is. It would leave the
>>>>>>whole
>>>>>>>>>> system in an unpredictable state. I cannot imagine anyone really
>>>>>>wanting
>>>>>>>>>> this.
>>>>>>>>>>
>>>>>>>>>>
>>>>>>>>>>>>> So shouldn't we just make --cplus turn *all* external
>>>>functions
>>>>>>and
>>>>>>>>>>>>> methods
>>>>>>>>>>>>> (whether C-like or C++-like) into "except +"? (Or keep
>>>>except+
>>>>>>for
>>>>>>>>>>>>> manual
>>>>>>>>>>>>> translation, but always have a catch(...)".
>>>>>>>>>>>>>
>>>>>>>>>>>>> Performance overhead is the only reason I can think of to not
>>>>>>do this,
>>>>>>>>>>>>> although IIRC C++ catch blocks are only dealt with during
>>>>stack
>>>>>>>>>>>>> unwinds and
>>>>>>>>>>>>> doesn't cost anything/much (?) when they're not triggered.
>>>>>>>>>>>>>
>>>>>>>>>>>>> "except -1" should then actually mean both; "except + except
>>>>>>-1". So
>>>>>>>>>>>>> it's
>>>>>>>>>>>>> more a question of just adding catch(...) *everywhere*, than
>>>>>>making
>>>>>>>>>>>>> "except
>>>>>>>>>>>>> +" the default.
>>>>>>>>>>>>
>>>>>>>>>>>>
>>>>>>>>>>>> I have no idea if there is a performance impact, but if there
>>>>>>isn't,
>>>>>>>>>>>> always
>>>>>>>>>>>> catching all exceptions sounds like a reasonable thing to do.
>>>>>>After
>>>>>>>>>>>> all, we
>>>>>>>>>>>> have no support for catching C++ exceptions on user side.
>>>>>>>>>>>
>>>>>>>>>>>
>>>>>>>>>>> This is a bit like following every C call with "except *"
>>>>(though
>>>>>>the
>>>>>>>>>>> performance ratios are unclear). It just seems a lot to wrap
>>>>>>every
>>>>>>>>>>> single line of a non-trivial C++ using function with try..catch
>>>>>>>>>>> blocks.
>>>>>>>>
>>>>>>>>
>>>>>>>> It seems "a lot" of just what exactly? Generated code? Binary
>>>>size?
>>>>>>Time
>>>>>>>> spent in GCC parser?
>>>>>>>
>>>>>>> All of the above. And we should take a look at the runtime overhead
>>>>>>> (which is hopefully nil, but who knows.)
>>>>>>>
>>>>>>>> Though I guess one might want to try to pull out the try-catch to
>>>>at
>>>>>>least
>>>>>>>> only one per code line rather than one per SimpleCallNode.
>>>>>>>
>>>>>>> Or even higher, if possible. It's still a lot.
>>>>>>
>>>>>>Why would you have to do that? Can't you just insert a try/catch per
>>>>>>try/except or try/finally block, or if absent, the function body.
>>>>That
>>>>>>will still work with the way temporaries are cleaned up. (It should
>>>>>>also be implemented for parallel/prange sections).
>>>>>
>>>>> One disadvantage is that you don't get source code line for the .pyx
>>>>file in the stack trace. Which is often exactly the information you are
>>>>looking for (even worse, since C++ stack isn't in the stack trace, the
>>>>lineno for what seems like the ' ultimate cause' is not there). Having
>>>>to surround statements with try/except just to pinpoint which one is
>>>>raising the exception would be incredibly irritating.
>>>>>
>>>>> Dag
>>>>
>>>>Oh yeah, good point. Maybe we could use these zero-cost exceptions for
>>>>cdef functions in Cython though, instead of error checks (if it
>>>>appears to make any significant difference). Basically instead of the
>>>>'error' argument in CEP 526. It'd need version that ABI as well...
>>>>
>>>
>>> Wait, one can just do
>>>
>>> lineno = 25;
>>> a()
>>> linono = 27;
>>> b()
>>>
>>> And wrap the block with a try catch.
>>
>> Heh, I just had the same idea before going to bed yesterday :) But it
>> means the common case (no exception) will get some overhead. That can
>> probably be afforded since normal error checking branches anyway.
>> Maybe it's worth investigating how many instructions try/catch blocks
>> generate and seeing whether a) it's (significantly) better than
>> branching and b) whether a try/catch block can be afforded per
>> subexpression/lineno.
>
> For sure some performance testing needs to be done to move this
> significantly forward.
>
>>> I'm not sure if I like C++ exceptions internally in Cython myself. It would mean that C-compiled Cython modules would not be able to call C++-compiled Cython modules, which I think would create a lot of headache. And I think we want to keep the ability to compile with a C compiler if you don't call C++ code...
>>
>> I don't know how often people mix the two. It's probably not worth
>> making a directive either... Are there any platforms where installing
>> a C++ compiler is more of a hassle than a C compiler? E.g. Theano
>> depends on a C++ compiler (and a lot more as well).
>
> Are you implying, for example, that one would have to re-compile NumPy
> with a C++ compiler if you wanted to use any C++ extension modules?
> I'd rather avoid this.

No, you can still freely mix any extension modules, it's just that
when you cimport stuff from other Cython modules, they have to be ABI
compatible. If C++ is part of the ABI due to how exceptions are
propagated and handled, then those modules need to be compiled both
with C++ (or neither, to get the other semantics with slower (to be
verified) error checks).

>> The cool thing about it would be that as you said earlier in the
>> thread, you could at the very least do one try/catch per line number,
>> so you wouldn't need N branches for N subexpressions that can fail.
>>
>>> Dag
>>>
>>>>>>
>>>>>>>> "except *" only has a point when calling functions using the
>>>>CPython
>>>>>>API,
>>>>>>>> but most external C functions are pure C, not
>>>>>>CPython-API-using-functions.
>>>>>>>> OTOH, all external C++ functions are C++ :-)
>>>>>>>
>>>>>>> Fair point.
>>>>>>>
>>>>>>>> (Also, if we wrote Cython from scratch now I'm pretty sure the
>>>>>>"except *"
>>>>>>>> defaults would be a tad different.)
>>>>>>>
>>>>>>> For sure.
>>>>>>>
>>>>>>>>>> But if users are correct about their declarations, we'd end up
>>>>>>with the
>>>>>>>>>> same thing. I think it's worth a try.
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> Most C++ code (that I've ever run into) doesn't use exceptions,
>>>>>>>>> because exception handling is so broken in C++ anyways.
>>>>>>>>
>>>>>>>>
>>>>>>>> Except for the fact that any code touching "new" could be raising
>>>>>>>> exceptions? That propagates.
>>>>>>>
>>>>>>> I would guess most of the time people don't bother catching these
>>>>and
>>>>>>> let the program die, as there's often no sane recovery (the same as
>>>>>>> MemoryErrors in Python, though I guess C++ is less often used from
>>>>an
>>>>>>> event loop).
>>>>>>>
>>>>>>>> There is a lot of C++ code out there using exceptions. I'd guess
>>>>>>that both
>>>>>>>> mathematical code and Google-written code is unlike most C++ code
>>>>>>out there
>>>>>>>> :-) Many C++ programmers go on and on about RAII and auto_ptrs and
>>>>>>so on,
>>>>>>>> and that doesn't have much point unless you throw an exception now
>>>>>>and then
>>>>>>>> (OK, there's the occasional return statement where it matters
>>>>well).
>>>>>>>
>>>>>>> True, I've seen a small subset of the C++ code that's out there.
>>>>>>Maybe
>>>>>>> numerical computations use it a lot?
>>>>>>>
>>>>>>> +1 to making catch-everywhere a directive at least. Lets see what
>>>>the
>>>>>>> impact is before we decide to make it the default.
>>>>>>>
>>>>>>> - Robert
>>>>>>> _______________________________________________
>>>>>>> cython-devel mailing list
>>>>>>> cython-devel at python.org
>>>>>>> http://mail.python.org/mailman/listinfo/cython-devel
>>>>>>_______________________________________________
>>>>>>cython-devel mailing list
>>>>>>cython-devel at python.org
>>>>>>http://mail.python.org/mailman/listinfo/cython-devel
>>>>>
>>>>> --
>>>>> Sent from my Android phone with K-9 Mail. Please excuse my brevity.
>>>>> _______________________________________________
>>>>> cython-devel mailing list
>>>>> cython-devel at python.org
>>>>> http://mail.python.org/mailman/listinfo/cython-devel
>>>>_______________________________________________
>>>>cython-devel mailing list
>>>>cython-devel at python.org
>>>>http://mail.python.org/mailman/listinfo/cython-devel
>>>
>>> --
>>> Sent from my Android phone with K-9 Mail. Please excuse my brevity.
>>> _______________________________________________
>>> cython-devel mailing list
>>> cython-devel at python.org
>>> http://mail.python.org/mailman/listinfo/cython-devel
>> _______________________________________________
>> cython-devel mailing list
>> cython-devel at python.org
>> http://mail.python.org/mailman/listinfo/cython-devel
> _______________________________________________
> cython-devel mailing list
> cython-devel at python.org
> http://mail.python.org/mailman/listinfo/cython-devel


More information about the cython-devel mailing list