Search code examples
c++visual-studio-2017stack-overflow

Remainder of a division with c++ getting 'Stack Overflow' exception


I'm trying to understand some concepts in C++, and I made this code to get the remainder of a division (like % operator):

double resto(double a, double b) {
    if (a == b) return 0;
    else if (a < b) return a;
    else {
        return resto(a-b, b);
    }
}

When I run it with lowers numbers like (12,3) or (2,3), it runs fine. But if I try to run it with the parameters (2147483647 * 1024, 3) I get:

Stack overflow (parameters: 0x0000000000000001, 0x000000F404403F20)

As I'm new in C++, I'm not sure if it's something with Visual Studio 2017 or it's the compiler, or stack memory, etc.


Solution

  • resto(2147483647 * 1024, 3); 
    

    is going to recurse 2147483647 * 1024 / 3, or about 733 billion, times. Every recursive call is using a small amount of Automatic storage for parameters and book-keeping and the program will likely run out of storage before it reaches even a million iterations.

    For this you will have to use a loop or smarter logic (for example subtracting larger multiples of b until using smaller numbers begins to make sense), but fmod is probably going to be faster and more effective.

    Other notes:

    2147483647 * 1024
    

    is an integer times an integer. This math will take place in ints and overflow if int is 16 or 32 bit on your system. Exactly what happens when you overflow a signed integer is undefined, but typically the number does a 2s compliment wrap-around (to -1024 assuming 32 bit integer). More details on overflowing integers in Is signed integer overflow still undefined behavior in C++?. Use

    2147483647.0 * 1024
    

    to force floating point numbers.

    Also watch out for Is floating point math broken? Floating point is imprecise and it's often difficult to get to floating point numbers that should be the same to actually be the same. a == b is often false when you expect true. In addition if one number gets too much larger than the other a-b may have no visible effect because b is lost in the noise at the end of a. The difference between the two cannot be represented correctly.