1

I am writing a simple C++ Program which allocates dynamic memory to my Program and then deletes this memory. Here is my Program:

#include <iostream>
#include <new>
using namespace std;

int main ()
{
  int i,n;
  int * p;
  cout << "How many numbers would you like to type? ";
  cin >> i;
  p= new (nothrow) int[i];
  if (p == nullptr)
    cout << "Error: memory could not be allocated";
  else
  {
    for (n=0; n<i; n++)
    {
      cout << "Enter number: ";
      cin >> p[n];
    }
    cout << "You have entered: ";
    for (n=0; n<i; n++)
      cout << p[n] << ", ";
    delete[] p;
  }
  return 0;
}

In the above program when I input the value of i (Number of inputs) equal to or less than 2 Billion than this program works as expected. However when I enter anything above 2 Billion like 3 Billion or higher, this program goes in an infinite loop without taking a number input in my for loop.

I am expecting this program to fail when I enter a very high value for i by saying it could not allocate the memory.

As per my understanding, I think when I enter a very high value of int i, I am going out of bound for integer data type but still in this case, it should take number input from me in for loop as I have a cin statement there instead of going in for loop or memory allocation should fail simply.

When I changed type of i from int to long then it works but I am curious to know for i of type int, why it goes in infinite loop instead of taking values when it sees cin in for loop?

I am running this program on Mac OS X and compiling it using g++ compiler.

jww
  • 97,681
  • 90
  • 411
  • 885
Prabhash Rathore
  • 709
  • 10
  • 18
  • Let's say even if i becomes -1 then in that case, my for loop to input number should not execute at all and then program should terminate, right? It should not go in infinite loop, I would think? – Prabhash Rathore Feb 15 '15 at 23:39
  • 1
    This isn't an answer, but since you only want the user to enter positiv numbers you should use `unsigned int` or perhaps `unsigned long` instead of `int`. – Cyclonecode Feb 15 '15 at 23:43
  • Have you tried to check the value of i in the debugger or write it by cout? – Piotr Siupa Feb 15 '15 at 23:46
  • 1
    What you're missing is that `cin` is an object that has a state. That state can be good, bad, fail, or eof. You should add error checking to make sure after you read user input that your `cin` state is still good before invoking `>>` on it again. A *good* C++ tutorial will explain how. The suggestions here to change data types are completely missing the point and you will *still* have this problem, just with different values of user input. – indiv Feb 15 '15 at 23:47
  • Use size_t if you need such huge sizes. – Neil Kirk Feb 15 '15 at 23:51
  • Generally, if you want to handle such a large numbers, you should use long long int (or something from for better portability). – Piotr Siupa Feb 15 '15 at 23:54
  • @NO_NAME Why not size_t which will be large enough for the job? – Neil Kirk Feb 15 '15 at 23:57
  • 1
    @NeilKirk I can not find precise information but `size_t` has only 4 bytes on my computer. It is an alias to `unsigned int`. Even if other compilers give it a bigger size, this solution is not portable. – Piotr Siupa Feb 16 '15 at 00:05
  • 1
    @NO_NAME `size_t` is guaranteed to be large enough to hold the size of the largest possible contiguous array. This program is allocating contigous arrays. Why is that not portable? – Neil Kirk Feb 16 '15 at 00:07
  • 1
    @NO_NAME: That's right, `size_t` doesn't solve the original problem. But on the other hand, suggesting `long long int` or whatever doesn't work either in this program because the prototype to malloc is `void *malloc(size_t size);`. You'd just be truncating whatever massive number the user typed. – indiv Feb 16 '15 at 00:09
  • @indiv Why doesn't size_t solve the problem? – Neil Kirk Feb 16 '15 at 00:10
  • @NeilKirk: Because what if the user types 5 billion? Or "two". Or -700? – indiv Feb 16 '15 at 00:10
  • That's what the code which checks the number was parsed successfully and outputs an error message if it didn't, is for. But there isn't any.. There is more to do than change the type of a variable here, but on that matter, `size_t` is the correct type for that variable. – Neil Kirk Feb 16 '15 at 00:11
  • So when I see the value of i during runtime, it's printed as 2147483647 which is the highest value for signed int. Looks like my cin object in for loop is acting up in this case but why would it blow up for only high value of i. – Prabhash Rathore Feb 16 '15 at 00:17
  • Also I was expecting to get Memory could not be allocated error but looks like I need to try long i instead of int to reproduce this scenario. – Prabhash Rathore Feb 16 '15 at 00:18

2 Answers2

1

1) You are trying assign to int value bigger than 2147483647, which is usually maximum value for this type. Generally, if you want to handle such a large numbers, you should use long long int (or something from <cstdint> for better portability).

2) You don't clear state of cin after it fails. The code bollow generate infinite loop:

int i = 0;
while (i <= 0)
{
    std::cout << "Enter a number greater than 10..." << std::endl;
    std::cin >> i;
}

You can solve it this way:

int i = 0;
while (i <= 0)
{
    std::cout << "Enter a number greater than 10..." << std::endl;
    if (!(std::cin >> i))
    {
        std::cin.clear();  // Clear error flag
        std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');  // Remove incorrect data from buffer
    }
}

3) You are trying to create a really big array. You need a few GiB of contiguous memory to this. Even if you succeed allocate the array, it is still a design issue. You should use many of smaller arrays or use/create a suitable container.

Piotr Siupa
  • 3,929
  • 2
  • 29
  • 65
  • You mean maximum value of `int` for this particular compiler. You should use `std::cin.ignore(std::numeric_limits::max(), '\n');` to clear the entire buffer. Why not the smaller `if (! (std::cin >> i))`? #3 depends. I've allocated multi-gigabyte arrays before for specialist purposes. – Neil Kirk Feb 16 '15 at 00:40
  • Good observations. I'll change it. – Piotr Siupa Feb 16 '15 at 00:43
  • @NeilKirk The third point is not corrected, because I still believe that the allocation of such a large array is a design issue. It not so hard to write own container, which behave like ordinary array. – Piotr Siupa Feb 16 '15 at 00:53
  • 1
    What happens if my machine has dozens of gigabytes of ram and I need to load 10gb of data and processing speed is important? (ie minimize indirections) – Neil Kirk Feb 16 '15 at 00:55
  • 1
    @NeilKirk OK, you have right. But I won't change my answer :P Beginners, who will be reading this, they should not take on bad habits. – Piotr Siupa Feb 16 '15 at 00:58
  • So in this case, cin object was the culprit. After clearing the state of cin object, my program works fine. Thank you! – Prabhash Rathore Feb 16 '15 at 06:29
0

The maximum value of a 32 bit signed integer is 2^31-1, namely 2147483647. Now, if you assign a higher value to an Int variable the behaviour is quite unexpected, try and see what i actually contains.

BTW, what do you mean by "infinite loop"? Does the program crash or does it never end executing?

cwbrd
  • 547
  • 1
  • 4
  • 10
  • It doesn't crash. I keeps printing "Enter Number: " string infinitely without terminating or waiting for cin input. – Prabhash Rathore Feb 15 '15 at 23:58
  • I printed the value of i and it's shown as 2147483647 which is the highest possible value for a signed int. But still it should not go in infinite loop. Seems there is something wrong with my cin object as pointed out by @indiv above. – Prabhash Rathore Feb 16 '15 at 00:14
  • 1
    @PrabhashRathore Are you sure it's in a truly infinite loop, and not just a loop of a few billion? – Neil Kirk Feb 16 '15 at 00:16
  • @PrabhashRathore: I found a good explanation for you: http://stackoverflow.com/questions/5864540/infinite-loop-with-cin – indiv Feb 16 '15 at 00:19
  • @Neil Kirk: I think you are right. It could be a loop of billion count. I tried to let my program run for a few minutes for it to crash or terminate but it kept running so thought it's running infinitely but it could just be a billion count loop. Let me verify the count of the loop. – Prabhash Rathore Feb 16 '15 at 00:22
  • @NeilKirk: I verified my program and it's not really an infinite loop but a loop running for billion times. – Prabhash Rathore Feb 16 '15 at 06:19
  • @indiv: Thank you for sharing cin stackoverflow link, that was helpful! – Prabhash Rathore Feb 16 '15 at 06:28