数组大小超过函数大小(C++)

Array size exceeds function size (C++)

本文关键字:C++ 数组 函数      更新时间:2023-10-16

让我首先说一下,我对编程总体来说还很陌生。解决方案可能非常明显。

基本上,我需要写一个代码,随机生成1到500之间的10000个数字(有些数字会在整个数组中重复。问题是,要给所述数组赋值,我想把它放在int类型的函数中,然后从那里开始,但数组根本不适合这个函数。在这种情况下,有没有办法用一个循环给数组中的所有变量赋值?可以在函数之外完成吗?

如果我尝试从函数调用它,我会收到以下两条警告消息:

1)警告C6262函数使用堆栈的"40012"字节:超过/analyze:stacksize"16384"。考虑将一些数据移动到堆中。

2)警告C6201索引"10000"超出了可能由堆栈分配的缓冲区"numsinarray"的有效索引范围"0"到"9999">

编辑:我在视觉工作室2019 工作

这是代码

#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);
}
}

欢迎使用堆栈溢出,具有讽刺意味的是,这里的问题是堆栈溢出
在这个代码片段中,您将分配4个字节的10'000整数,总共40'000字节,这对于堆栈中的某些内容来说是一个很大的数目。

int numsinarray[AmountOfNum];

堆栈是什么?:
堆栈是操作系统为执行程序而分配的内存区域,也是保存本地变量、函数调用、返回值等的地方。。。这有助于跟踪函数调用,以及CPU运行完函数后返回的位置。

我的问题的解决方案是什么?:(动态内存)
解决方案很简单,但也有责任心。每当你试图分配一些大的东西时,你都必须考虑堆。堆是一个你可以获得操作系统和PC所能处理的内存的地方。

如何从堆中进行分配

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

就这么简单,但还记得我前面提到的责任吗?每当你从堆中分配时,你必须明确地释放你在完成它时保留的内容(不再需要数据)

如何释放

delete[] numsinarray;

语法为:

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

然后你的代码将是:

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;
}

确保你没有双重释放指针或释放后再次使用它。

这听起来很复杂,还有其他选择吗
遗憾的是,要想成为一名优秀的程序员,你必须处理堆,但如果你在寻找其他解决方案,标准库(STL)会为我们提供std::vector,它更容易为你操作、处理和自动处理堆问题。

int numsinarray[AmountOfNum];

您正在调用堆栈上静态分配(sizeof(int)*AmountOfNum)=(4*10000)=40000字节,但项目的堆栈大小设置为16384字节。按照警告所说的那样,使用new[]std::vector在堆上动态分配数组。

用于(int i=0;i<=AmountOfNum;i++)

数组为0索引。数组的有效索引是0.9999,但循环使用<=而不是<会使其尝试写入索引10000,从而超出数组的范围进入周围的内存。

试试这个:

#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 ...;
}

应该认真对待编译器发出的警告(我将在下面处理这些警告)。它还应该给您至少一个其他警告:您的函数NumGen被声明为(返回)int,但它实际上没有返回任何内容!

您将遇到的另一个问题是,您无法访问在函数中"创建"的数组numsinarry。要解决此问题以及其中一个警告,您应该声明(并定义)"NumGen"函数为返回指向int的指针-然后您可以将返回的指针作为数组访问。

因此,这里有一个可能的版本(我添加了三斜杠注释,并在其中添加了一些注释):

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!
}

"创建"numsinaarry(称为自动变量)的问题是,当调用函数时,编译器将(试图)从分配给函数的内存中为其分配空间;这就是所谓的堆栈,从您引用的警告来看,它在您的平台上的限制为16384字节(16KB)。使用"new"运算符从我们所称的中分配所需的内存(40000字节),这实际上是程序可用的内存总量(目前是巨大的)。

当您最终从main调用此函数时,您将执行以下操作:

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

然后,您可以使用普通索引系统访问data"数组"的一个元素,如:int test = data[123];

还有一件非常重要的事情:在某个时刻,你永远不应该忘记释放分配的内存!释放使用new[]运算符分配的内存的方法是使用"delete[]"运算符,如下所示(当您处理完数据时):

delete[] data;

请随时要求任何进一步的澄清和/或解释。