Memory limit and infinite loop.

Pages: 12
The program to determine wind direction works fine. It calls out an error message when outside 0 to 360 degrees and gives the correct direction within that range.

Problem is when entering a number somewhere between 1,111,111,111 and 2,222,222,222 the result is an infinite loop that prints a fast scrolling result. This tells me there is a number limit beyond which the computer does not recognize.

My calculation for a 32 bit variable limit is 4,294,967,296. Ten 2's is less than that so why the problem?
If 0 - 360 is an angle, you could allow the user to input outside of that and just convert to 0 - 360.

Other than that, without code, it's hard to tell how "between 1,111,111,111 and 2,222,222,222" is affecting your program.
This bit in your code
1
2
3
4
5
6
while (inputNumber > 1111111111 && inputNumber < 2222222222)
{...



}

will cause an infinite loop as you described. If your code doesn't contain that, ignore this post; I have to guess as it's very tricky to read your code without you posting any of it.
Last edited on
Thanks roberts but I discovered the problem which leads to another question.

The type declared was int which accounts for + and - numbers in memory. When I divided the 32 bit number by 2 and entered that number the result crashed, BUT when I reduced that number by one it ran correctly so I exceeded a memory limit.

Question:

How do developers prevent a crash like this? The user input (cin) occurs ahead of the conditional statement of between 0 and 360. A user could enter a crazy number with undesirable results. Isn't it the job of the developer to account for all scenarios and prevent it?

So, how do I prevent the crash?

Thanks.

Last edited on
A circle is nice and continuous, so an angle of 720 is actually back at the 360 position, having traveled twice around.

Also, it's important to note that 0 == 360 on a unit circle (what we geometry geeks use to represent angles).

If you want to start at 0, then the unit circle is 0 - 359. If you start at 1, then it is 1 - 360.
Last edited on
Roberts: my task is not equivalent to a periodic trig function.

Moschops: I have a conditional statement that tests input within 0 - 360. All others display an error.

What I seek is what I assume a developer would create to PREVENT a crash.

Looking for code to IDIOT PROOF the program. Mine and Moschops code does NOT do this.

Stated another way, if this were a real world product design situation that must GUARANTEE no crashes, then there must be a trick to prevent possible product damage.

I would think software testers do this everyday.

Any ideas to attack the problem to prevent memory exceedence from idiots?

Any suggestions welcome.

Many thanks.

Roberts: my task is not equivalent to a periodic trig function.


My apologies. I thought the 0-360 was degress on a compass.
It is.

I wondered what if someone wanted to enter a wild illogical value. The result was a crash.

I want to design into the code a way to prevent this. This philosophy has to be the foundation of any development program.
Get input from user. If number is less than zero or greater than 360 or not a number, reject it and repeat.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <iostream>
#include <limits>

using namespace std;
int main()
{

  int input, acceptable;
  acceptable = 0;

  while(!acceptable)
  { 
       cout << "Please enter integer between 0 and 360: " << flush;

       if (!(cin >> input)) {
          cout << "You did not enter an int" << endl;}
       else if ( input < 0) {cout << "Must not be negative";}
       else if (input > 360) {cout << "Must not be greater than 360";}
       else (acceptable = 1);

       cin.clear();cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
  }
  return 0 ;
}
Last edited on
Ok, but even if you don't want to use a periodic compass, 0 still equals 360, even on a compass.
That was my intent. I am asking for much more. See the do while loop? Doesn't that cover all numeric cases? Expect for memory exceedence which is the reason I posted the question originally.

Thanks.



#include <iostream>
using namespace std;

void main()
{
int wdir, a, b;

do
{
cout << "Enter the wind direction in degrees." << endl << endl;
cin >> wdir;

if(wdir >= 0 && wdir <=360)
break;
else cout << "Unacceptable value. Try again." << endl;
} while (1); // the need to make while true when the value is unacceptable.

a=23, b=67;
for (int i=1; i<9; i++) // for the case number
{
if (wdir >= a && wdir <=b) // determines which case.

{ switch (i)
{
case 1: cout << "Wind direction is NE" << endl;
break;
case 2: cout << "Wind direction is E" << endl;
break;
case 3: cout << "Wind direction is SE" << endl;
break;
case 4: cout << "Wind direction is S" << endl;
break;
case 5: cout << "Wind direction is SW" << endl;
break;
case 6: cout << "Wind direction is W" << endl;
break;
case 7: cout << "Wind direction is NW" << endl;
break;
case 8: cout << "Wind direction is N" << endl;
break;
}

}

cout << "i = " << i << endl <<endl;

if (wdir >= a && wdir <=b) // to break out of the for loop immediately when the switch is satisfied
{ break;
}

a=a+45;
b=b+45;
}
if
(wdir >= 0 && wdir <= 22)
{
cout << "Wind direction is for 0-22 deg N" << endl;
}

//this program results in an infinite loop if wdir is a large number. this should not be since
// the useable range is limited. Answer is don’t enter a value > 16 bits / 2 for signed variables. Looking to idiot proof this.

system("pause");

}

The problem is not overflowing the int.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include <iostream>
#include <limits>
using namespace std;

int main()
{
  int wdir = 16, a, b;

  do
  {
    cout << "Enter the wind direction in degrees." << endl << endl;

     if (cin >> wdir)
    {
       if(wdir >= 0 && wdir <=360)
         break;
       else cout << "Unacceptable value. Try again." << endl;
    }
     cin.clear();cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
   } while (1); // the need to make while true when the value is unacceptable.

  cout << "wdir = " << wdir << endl;
  a=23, b=67;
  for (int i=1; i<9; i++) // for the case number
  { 
    if (wdir >= a && wdir <=b) // determines which case.

    { switch (i) 
      {
         case 1: cout << "Wind direction is NE" << endl;
         break;
         case 2: cout << "Wind direction is E" << endl;
         break;	
         case 3: cout << "Wind direction is SE" << endl;
         break;
         case 4: cout << "Wind direction is S" << endl;
         break;
         case 5: cout << "Wind direction is SW" << endl;
         break;
         case 6: cout << "Wind direction is W" << endl;
         break;
         case 7: cout << "Wind direction is NW" << endl;
         break;
         case 8: cout << "Wind direction is N" << endl;
         break; 
       }

     } 

     cout << "i = " << i << endl <<endl;

     if (wdir >= a && wdir <=b) // to break out of the for loop immediately when the switch is satisfied
       { break; } 
     a=a+45;
     b=b+45;
   }
   if (wdir >= 0 && wdir <= 22)
   {
     cout << "Wind direction is for 0-22 deg N" << endl; 
   }
}
Last edited on
I'll give your suggestion a try but it does not answer my question from the 7:59 a.m. post this morning which stated:

"The type declared was int which accounts for + and - numbers in memory. When I divided the 32 bit number by 2 and entered that number the result crashed, BUT when I reduced that number by one it ran correctly so I exceeded a memory limit."

You say it isn't memory exceedance but I see otherwise. My program successfully executes when within the memory limits. Until someone can explain why the program displayed in the 2:58 p.m. post runs successfully for positive numbers < 2^16 and crashes for positive numbers >= 2^16 then this post remains an open item.

Note: I am not at the point of understanding

cin.clear();cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

at this time. That is a few chapters away.

The answer I seek with my limited knowledge is why does this program crashes for + numbers >= 2^16?

Once I understand that, then I'll pursue crash prevention after that.

Thanks for your time.
Last edited on

It does not crash. It repeats over and over. That's very different.

It does that because there is junk left in the input line. As much of the input line is read into the int as is sensible. If you put something in the input line that is not sensible, this leaves junk on the input line. This is not cleared away unless you actively do so.

then this post remains an open item.

Well that's going to keep me awake tonight.
Moschops:

I tried your

cin.clear();cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');

suggestion and it works. I noticed the ignore and in parenthesis' numeric limits so this is an override functionality of the numeric limits? Is that correct? If so, then I interpret the results both mine as yours as follows:

Mine crashed due to system defined limits. Yours worked due to overriding those limits.

If the intent is to avoid a crash, then I interpret these results being all programs need the cin.ignore function along with appropriate cout statements alerting of error inputs.

Unless this is incorrect, I consider my question closed.

Thanks for the new code. I'll keep an eye out for it.
Mine crashed due to system defined limits. Yours worked due to overriding those limits.


No, that is a very wrong interpretation. The program did NOT crash. It did NOT crash. It repeated endlessly because there was junk left in the input line, which was then read and NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed, and when it was found to be bad input, the section of code repeated, and read the junk from the input line which was NOT removed...

The code I added clears the input of the junk. That's it.
2^16 is out of the range of your variable.
Then the reading fails. That puts cin in an invalid state, and all subsequent readings fail too.
As you didn't initialize 'wdir' the condition is not meet, never.

The same would happen if you don't input an number. (by instance you write 'north')

cin.clear();cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n'); is to recover the stream.

How do developers prevent a crash like this? (...). A user could enter a crazy number with undesirable results. Isn't it the job of the developer to account for all scenarios and prevent it?
I like GIGO.
You can catch the error (by instance checking the state of cin), how you treat it is not obvious.
@ne555:

I tried your suggestion but you are incorrect that "all subsequent readings fail too."

You are correct in that entering north caused a crash. Numbers >= 2^16 require a cin.clear() for a successful run.

Any numerics within the defined memory range produces good results immediately after a crash WITHOUT the use of cin.clear(). So, why does this invalid state NOT affect numerics within limits?

Why is the initialization of wdir important when it will be input a value?

Thanks.



Last edited on
Any numerics within the defined memory range produces good results immediately after a crash WITHOUT the use of cin.clear(). So, why does this invalid state NOT affect numerics within limits?

I want to know how did you test that.
And as Moschops pointed out, it is not a crash.
A crash terminates your program. So saying 'produces good results after a crash' doesn't make sense.

Why is the initialization of wdir important when it will be input a value?
It is not. I worded it badly
if(wdir >= 0 && wdir <=360) break; will cut the loop. As the reading failed 'wdir' remainds with garbage.
If that garbage value satisfies the condition, you wouldn't have an infinite loop.
Incorrect choice of words. The problem is an infinite loop. I tested the following results without cin.clear(). If an infinite loop I abort, then recompile with a value within limits and the results are fine.

Puzzled by your last sentence. Garbage value yielding normal loop operation?

The solution seems to be the use of cin.clear() before every cin statement? I have not seen this presented in any of the material I am studying but if it is a good practice to do so then I will.
Pages: 12