2

Let me start by saying that I am quite new to programming in general. The solution might be really obvious.

Basically i need to write a code that randomly generates 10,000 numbers in between 1 and 500 (some numbers will repeat themselves throughout the array. Here is the problem, to give values to said array I meant to put it in a function of type int and go from there, but the array simply wont fit in the function. Is there a way to give a value to all the variables in the array using one loop in this case? can it be done outside a function?

If i try calling it from a function, I get those 2 warning messages:

1) Warning C6262 Function uses '40012' bytes of stack: exceeds /analyze:stacksize '16384'. Consider moving some data to heap.

2) Warning C6201 Index '10000' is out of valid index range '0' to '9999' for possibly stack allocated buffer 'numsinarray'

edit: i work on visual studio 2019

Here's the code

#include <iostream>
#include <random>
using namespace std;
std::random_device seed;
std::mt19937 mersenneTwister(seed());
const int AmountOfNum = 10000;

const int RandomInt(int min, int max);
int NumGen(int min, int max);

int main()
{





}

const int RandomInt(int min, int max)
{
    std::uniform_int_distribution<int> distribution(min, max);
    return distribution(mersenneTwister);
}

int NumGen(int min, int max)
{
    int numsinarray[AmountOfNum];

    for (int i = 0; i <= AmountOfNum; i++)
    {
        numsinarray[i] = RandomInt(1, 500);

    }

}
HalpPlease
  • 29
  • 3
  • Hmm. Your code looks okay, other than the array might be too big for your platform as the error says. Just for completeness, what platform are you on? –  Oct 27 '19 at 22:45
  • 1
    You need to use the operator new to allocate enough space on the heap you're overflowing the sack. – Omarito Oct 27 '19 at 22:46
  • I work on visual studio 2019. Do you mean replacing the array's variable by a new? – HalpPlease Oct 27 '19 at 22:47
  • 1
    You should use `std::vector` instead of `new` directly – Remy Lebeau Oct 27 '19 at 22:54

3 Answers3

2

Welcome to Stack overflow, ironically the problem here is about overflowing the stack.
In this code snippet you're allocating 10'000 integer of 4 bytes which is 40'000 bytes in total which is a lot for something to be in the stack.

int numsinarray[AmountOfNum];

What's the Stack ?:
The stack is the zone of memory allocated by your OS to execute your program its the place where the local variables are held, functions calls, return values, etc... Which help keep track of function calls and where to return when your CPU finish running a function.

Whats the solution to my problem ?: (Dynamic memory)
The solution is simple but comes with responsibility. Whenever you try to allocate something big you have to think of the Heap.The heap is the place where you can get memory as much as your OS and PC can process.

How to allocate from the heap ?

int* numsinarray = new int[AmountOfNum]; // syntax : TYPE* ptr = new TYPE[NB];

it's as simple as that, but remember the responsibility I mentioned earlier ? Whenever you allocate from the heap you have to explicitly free what you reserved when you are done with it (don't need the data anymore)

How to free ?

delete[] numsinarray;

the syntax is:

delete[] ptr; // if its an array or 
delete ptr; // if you allocate only one element

Your code then will be :

int main()
{
   int* my_arr = NumGen(0, 500);
   // use my array.. more code...
   delete[] my_arr; // free my array I dont need it anymore
}

int RandomInt(int min, int max) // the const here is useless (I removed it)
{
    std::uniform_int_distribution<int> distribution(min, max);
    return distribution(mersenneTwister);
}

int* NumGen(int min, int max)
{
    int* numsinarray = new int[AmountOfNum];

    for (int i = 0; i < AmountOfNum; i++) // must be < not <= the latter will reach AmountOfNum 
         //which is already out of the array (array's in C/C++ are indexed in [0..n-1]
    {
        numsinarray[i] = RandomInt(1, 500);

    }
    //  do more processing maybe return the pointer of you array
    return numsinarray;
}

Make sure you don't double free the pointer or use it again after freeing it.

Any alternatives this sounds to be complicated ?
To be good programmer sadly you have to deal with the heap, but if your looking for other solutions the standard library (STL) provides us with std::vector that is simpler to manipulate, handle and automatically handle the heap troubles for you.

Omarito
  • 577
  • 6
  • 22
1

int numsinarray[AmountOfNum];

You are allocating (sizeof(int) * AmountOfNum) = (4 * 10000) = 40000 bytes statically on the call stack, but your project's stack size is set to 16384 bytes. Do as the warning says, allocate the array dynamically on the heap instead, using new[] or std::vector.

for (int i = 0; i <= AmountOfNum; i++)

Arrays are 0-indexed. The valid indexes for your array are 0..9999, but your loop's use of <= instead of < makes it try to write to index 10000, thus going out of bounds of the array into surrounding memory.

Try this:

#include <iostream>
#include <random>
#include <vector>

std::random_device seed;
std::mt19937 mersenneTwister(seed());
const int AmountOfNum = 10000;

const int RandomInt(int min, int max);
int NumGen(int min, int max);

int main() { }

const int RandomInt(int min, int max)
{
    std::uniform_int_distribution<int> distribution(min, max);
    return distribution(mersenneTwister);
}

int NumGen(int min, int max)
{
    std::vector<int> numsinarray(AmountOfNum);
    for (int i = 0; i < AmountOfNum; i++)
    {
        numsinarray[i] = RandomInt(1, 500);
    }

    /* alternatively:

    std::vector<int> numsinarray;
    numsinarray.reserve(AmountOfNum);
    for (int i = 0; i < AmountOfNum; i++)
    {
        numsinarray.push_back(RandomInt(1, 500));
    }
    */

    // use numsinarray as needed...

    return ...;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
0

The warnings given by your compiler should be taken seriously (I'll deal with these below). It should also give you at least one other warning: that your function, NumGen is declared as (returning an) int but it doesn't actually return anything!

Another problem you will encounter is that you have no way to access the array numsinarry that you 'create' in the function. To address this, and one of the warnings, you should declare (and define) the 'NumGen` function as returning a pointer to int - you can then access that returned pointer as an array.

So, here's one possible version (I've added triple-slash comments with some notes where I've made changes):

int* NumGen(int min, int max) /// Use int* to say we shall return a pointer (array)¬
{
//  int numsinarray[AmountOfNum]; /// This is too big for the "stack" - see below.
    int *numsinarry = new int[AmountOfNum]; /// This creates the 'array' on the "heap"

//  for (int i = 0; i <= AmountOfNum; i++) /// This goes one beyond the end of the array
    for (int i = 0; i < AmountOfNum; i++)  /// The last element has index AmountOfNum - 1
    {
        numsinarray[i] = RandomInt(1, 500);
    }
    return numsinarry; /// Return this so we can use the data!
}

The problem with your 'creation' of numsinaarry (what's called an automatic variable) is that the compiler will (try to) assign space for it from memory assigned to the function when it is invoked; this is what is known as the stack and, from the warning you have quoted, it has a limit of 16384 bytes (16 KB) on your platform. Using the 'new' operator allocates the memory required (40,000 bytes) from what we call the heap - which is, effectively, the total amount of memory available to your program (these days, massive).

When you eventually call this function from main, you will do something like this:

int *data = NumGen(1, 500); // These are the limits for min & max you indicated!

And you can then access an element of the data 'array' using the normal indexing systems, like: int test = data[123];.

One more very important thing: You should never forget, at some point, to release the memory allocated! The way to free memory allocated with the new[] operator is to use the 'delete[]` operator, like this (when you've finished with the data):

delete[] data;

Feel free to ask for any further clarification and/or explanation.

Adrian Mole
  • 49,934
  • 160
  • 51
  • 83