Page 1 | Page 2 | **Page 3** | Page 4

## Division by zero

Another common cause for crashes is devision by zero. In a nutshell:

*You shall not divide by zero!*

In many cases, it is obvious if the code is prone to Division By Zero crashes:

Real Ratio(Real x) { return RCO 1.0 / x; }

This function will – of course – crash when called with 0.0 as parameter value.

You have to check x for 0.0 first and only perform the devision if x is not 0.0.

Real Ratio(Real x) { if (x == RCO 0.0) return RCO 0.0; return RCO 1.0 / x; }

A lot better… you might think. But keep in mind that floating point values only have a limited precision. A value might be so small that is crashes even if it’s not exactly 0.0.

Therefore, it is better to use a function like CompareFloatTolerant() from the CINEMA 4D API.

Real Ratio(Real x) { if (CompareFloatTolerant(x, RCO 0.0)) return RCO 0.0; return RCO 1.0 / x; }

In practice, if you have a more complex calculation that is time-critical (e.g. a shading algorithm), you will want to ensure valid values before the calculation starts. Calling CompareFloatTolerant() all the time might have an impact on the performance (depending on how your algorithm works and in which context it is called).

However, there are cases where it is not as obvious that a division by zero might occur.

For example, we have a GeUserArea, and we want to draw a grid of items into it. The width of the grid cells is fixed to 150 pixel, so we can calculate the number of grid columns from the UserArea’s width and the column width, and the number of grid rows from the number of columns and the number of items to draw.

Bool MyUserArea::GetMinSize(LONG& w, LONG& h) { w = 100; h = 100; return TRUE; } Bool MyUserArea::DrawMsg(LONG x1, LONG y1, LONG x2, LONG y2, const BaseContainer& msg) { // Calculate number of columns from width of UserArea and column width _columns = GetWidth() / 150; // Calculate number of rows from number or columns and number of items _rows = _items.GetCount() / _columns; // ... }

Where could this code crash? Of course, you might say, I can’t just divide by *_columns*, because *_columns* can be zero. But wait, why would *_columns* be zero? We calculate its value by dividing the width of the GeUSerArea by 150. It could only be zero, if the UserArea’s width is zero, too. And that, again, should never happen, since we have set the UserArea’s minimum size to 100×100 pixel. Correct? No, wrong. In case, DrawMsg() is called before GetMinSize() under some weird circumstances, the width might still be zero. That would make *_columns* zero, too. And then it would crash.

This is just one of many examples where rare circumstances can lead to crashes that can be very hard to track down. Let’s remember the first sentence: *You shall not divide by zero!* Therefore, always check for zero before any division, even if there’s only the slightest chance that the divisor could be zero.

Bool MyUserArea::DrawMsg(LONG x1, LONG y1, LONG x2, LONG y2, const BaseContainer& msg) { // Calculate number of columns from width of UserArea and column width _columns = GetWidth() / 150; // Zero check if (_columns == 0) _columns = 1; // Calculate number of rows from number or columns and number of items _rows = _items.GetCount() / _columns; // ... }

Or shorter:

Bool MyUserArea:: { // Calculate number of columns from width of UserArea and column width _columns = GetWidth() / 150; // Calculate number of rows from number or columns and number of items _rows = _items.GetCount() / (_columns == 0 ? 1 : _columns); // ... }