0

Say I have a python module of the form .so and it contains something like this:

static PyObject* f(PyObject* _1, PyObject* _2) {
  int a = 0; 
  a = 1/a;
  return NULL;
}

After running Python will crash. The command line gives Floating point exception: 8.

And I also see this:

Python Crash

Is this a bug or is it possible to catch this error without change and recompile the .so file?

Jason
  • 2,278
  • 2
  • 17
  • 25
h__
  • 865
  • 1
  • 11
  • 19
  • 1
    For errors originating from your C code, you have to use C's facilities. – ivan_pozdeev Mar 08 '16 at 03:01
  • Related: http://stackoverflow.com/questions/3286448/calling-a-python-method-from-c-c-and-extracting-its-return-value – ivan_pozdeev Mar 08 '16 at 03:03
  • Adding to @ivan_pozdeev, when you're writing C extensions, it's _your_ job to _create_ the exceptions for Python to raise. When calling non-Python APIs, you're the only one with the information required to create the exceptions. – ShadowRanger Mar 08 '16 at 03:09

1 Answers1

1

Now sit back and remember what C code looks like at runtime. It's just compiled to machine code. When you divide by zero in it, it happens on machine code level - i.e. the CPU actually attempts it, generates a hardware interrupt which the OS handles and ultimately terminates your process.

Python code, on the other hand, is just random binary data at runtime that another code - the interpreter - looks at and determines what to do. When you divide by zero in it, the interpreter double-checks the divisor and prints a nice traceback before the CPU actually attempts the operation. The same goes for array bounds, object references etc.

In brief, at C level, there's no Python interpreter to babysit you. You need to check the input for validity yourself (for input originating from Python's runtime, however, there are library functions that ease the task). Likewise, if you wish to report an error to the Python runtime, you need to construct yourself and pass it an exception object with relevant info (exception type and parameters) for which, there's also a bunch of library functions.

ivan_pozdeev
  • 33,874
  • 19
  • 107
  • 152
  • Are you saying `try... catch` actually tries to detect the error instead of capture signals raised by CPU and handles it? That seems a bit weird to me. I can imagine it checking for things like index out of bound. But what if the error actually happens (e.g. `MemoryError` or failure on create sockets)? In that case the interpreter still do the babysit job? – h__ Mar 08 '16 at 10:54
  • @h__ The interpreter indeed detects errors from system on C level - by return value of a library function, signal etc., by "catching signals" - constructs and uses an exception object etc. For out of memory condition, there's [`PyErr_NoMemory`](https://docs.python.org/2/c-api/exceptions.html#c.PyErr_NoMemory) that can work in cases where allocation is not possible. Yes, _every_ `malloc` is checked. Division by zero is a special case because [there's no way to catch it in C](http://stackoverflow.com/questions/3105591/how-to-catch-the-integer-division-by-zero-exception-in-c-language). – ivan_pozdeev Mar 08 '16 at 15:19
  • ...oh rather, no _standard_ way. Most UNIXes send SIGFRE on that, and [Windows throws a SEH exception](http://stackoverflow.com/questions/1832809/how-to-catch-divide-by-zero-error-in-visual-studio-2008-c). I must confess I didn't actually check how exactly Python handles this case. The important part was, it does while C doesn't. – ivan_pozdeev Apr 06 '16 at 12:02