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

Posted

技术标签:

【中文标题】数组大小超过函数大小 (C++)【英文标题】:Array size exceeds function size (C++) 【发布时间】:2019-10-27 22:35:32 【问题描述】:

首先让我说我对编程很陌生。解决方案可能非常明显。

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

如果我尝试从函数中调用它,我会收到这 2 条警告消息:

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

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

编辑:我在 Visual Studio 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);

    


【问题讨论】:

嗯。您的代码看起来没问题,除了错误所说的数组对于您的平台来说可能太大了。为了完整起见,您在哪个平台上? 您需要使用 operator new 来在堆上分配足够的空间来溢出袋子。 我在 Visual Studio 2019 上工作。你的意思是用新的替换数组的变量吗? 你应该直接使用std::vector而不是new 【参考方案1】:

欢迎来到堆栈溢出,讽刺的是这里的问题是堆栈溢出。 在这段代码 sn-p 中,您分配了 10'000 个 4 个字节的整数,总共 40'000 个字节,这对于堆栈中的东西来说是很多的。

int numsinarray[AmountOfNum];

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

我的问题的解决方案是什么?:(Dynamic memory) 解决方案很简单,但也有责任。每当您尝试分配大的东西时,您必须考虑Heap。heap 是您可以获得尽可能多的内存的地方,因为您的操作系统和 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,它更易于操作、处理和自动处理堆问题。

【讨论】:

忍不住喜欢你的开场白!这绝对值得 ? 投票。【参考方案2】:

int numsinarray[AmountOfNum];

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

for (int i = 0; i

数组是从 0 开始索引的。您的数组的有效索引是 0..9999,但是您的循环使用 &lt;= 而不是 &lt; 使其尝试写入索引 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 ...;

【讨论】:

很好,但是您的int NumGen(int min, int max) 版本仍然没有返回任何内容!【参考方案3】:

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

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

所以,这是一个可能的版本(我添加了三斜线 cmets,并在其中进行了一些更改):

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(所谓的 自动 变量)的问题是编译器将(尝试)从分配给函数的内存中为其分配空间被调用;这就是所谓的 stack,根据您引用的警告,它在您的平台上的限制为 16384 字节(16 KB)。使用 'new' 操作符从我们称为 heap 的地方分配所需的内存(40,000 字节) - 实际上,这就是您的程序可用的内存总量(这些天,巨大的)。

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

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

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

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

delete[] data;

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

【讨论】:

以上是关于数组大小超过函数大小 (C++)的主要内容,如果未能解决你的问题,请参考以下文章

在没有向量、指针的情况下在 C++ 中在运行时增加数组大小 [关闭]

c++中用new给未知大小的数组分配空间怎么弄?

int 数组 C++ 的大小

Array.Sort 谷歌内核 数组大小超过10 排序字段都一致 返回的数组非原数组

我需要 C++ 数组类模板,它是固定大小、基于堆栈且不需要默认构造函数

以编程方式确定 C++ 数组的大小?