1

it's two days I cannot get around this problem. In the following code I am trying to generate uncaught exceptions in C++ code, wrap the C++ code in cython and cal the class methods in a python script. (I am on Windows if that matters)

I managed to catch, in python, the exceptions thrown by hand but in no way I can manage to catch zero division error or the stack overflow error generated in the c++ code, what am I missing?

Using: Python 3.6.4 and Cython 0.29.21

Build and launch command: python setup.py build_ext --inplace && python main.py

exceptions.h

#include <stdexcept>
#include <iostream>
#include <string>

using std::cout;
// Integer division, catching divide by zero.

inline int intDivEx (int numerator, int denominator) {
    if (denominator == 0)
        throw std::overflow_error("Divide by zero exception");
    return numerator / denominator;
}
class exceptions {
    public:
        void recursion_throw(int stack) {
            cout << "\t " << stack;
//            this->recursion(stack+1);
            if (stack<1000) this->recursion(stack+1);
            else {
                throw std::overflow_error("My Stackoverflow ERROR!");
            }
        }

        double division_throw(int value) {
            int ret_value = 0;
            try { ret_value = intDivEx(1, value); }
            catch (std::overflow_error e){
                cout << e.what() << " value: ";
            }
            std::cout << value << std::endl;

            return 0;
        }

        void recursion(int stack) {
            cout << "\t " << stack;
            this->recursion(stack+1);
        }

        double division(int value) {
            int ret_value = 0;
            ret_value = 1/value;
            return ret_value;
        }

};

test.pyx

# distutils: language = c++
import cython

from libcpp.string cimport string


cdef extern from "exceptions.h":
    cdef cppclass exceptions:
        void recursion_throw(int stack) except +
        double division_throw(int value) except +
        void recursion(int stack) except +
        double division(int value) except +


cdef class Exceptions:
    cdef exceptions excps


    def recursion(self):
        print("Running recursion")
        self.excps.recursion(0)

    def division(self, value):
        print("Running division")
        try:
            return self.excps.division(value)
        except Exception as e:
            print(e)

setup.py

from distutils.core import setup
from Cython.Build import cythonize


setup(ext_modules=cythonize("test.pyx"),)

main.py

#!/usr/bin/env python

import test
import traceback

if __name__ == '__main__':
    S = test.Exceptions()

    S.division(0)
    try:
        S.recursion()
    except RuntimeError as e:
        print()
        print(traceback.format_exc())
  • Does this answer your question? [Catching exception: divide by zero](https://stackoverflow.com/questions/6121623/catching-exception-divide-by-zero) – ead Jul 28 '20 at 10:18
  • The duplicate is for divide by zero, and says "you cannot". But the same applies for stack overflow. – ead Jul 28 '20 at 10:19
  • Duplicate for stack overflow: https://stackoverflow.com/q/1578878/5769463 – ead Jul 28 '20 at 10:25
  • My problem is not to catch the exception in C++, is to catch it in python! If the program is executed, the python interpreter just crashes abruptly without giving any stack trace. – walter zeni Jul 28 '20 at 10:27
  • Btw, `std::overflow_error` is not for stack overflow but for overflow in arithmetical operations. – ead Jul 28 '20 at 10:27
  • Well, your python-interpreter executes c++-code via call to the c++-extension, c++-code triggers stack overflow or division by zero (which is different from Python's stack overflow or division by zero) thus c++-rules apply: It is undefined behavior, so anything can happens: your Python-interpreter gets killed or your hard disk formatted - there is no guarantee... – ead Jul 28 '20 at 10:30
  • actually, cython should do the exception conversion all by himself! docs ref.: https://cython.readthedocs.io/en/latest/src/userguide/wrapping_CPlusPlus.html#exceptions – walter zeni Jul 28 '20 at 10:44
  • Please read the answers from the dupes: divide by zero and stack overflow aren't standard c++ exceptions (but undefined behavior) - so you cannot catch them and thus also cython will not do it for you (because it is not possible). – ead Jul 28 '20 at 10:55
  • Ah ok, got it! Thank you very much for the explanation. – walter zeni Jul 28 '20 at 14:37
  • So throwing exceptions across stack frames that are not exception aware is highly not recommended. You'll need to catch them prior to python and then re-raise them as python exceptions. – Mgetz Jun 25 '21 at 13:56

1 Answers1

0

Since you're on Windows, if you're using VS C++ compiler you can set the exception handling flag to enable SEH exceptions like this: /EHa

That will allow it to catch "hard" exceptions such as division by zero. Then in Python you'll see:

...
RuntimeError: Unknown exception

Which is not ideal, but still better than a silent crash.

tromgy
  • 4,937
  • 3
  • 17
  • 18