首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >数组中的混合元素:基于堆栈的缓冲区溢出错误

数组中的混合元素:基于堆栈的缓冲区溢出错误
EN

Stack Overflow用户
提问于 2017-07-02 07:45:04
回答 3查看 245关注 0票数 0

我给出的代码是原程序的问题部分。它随机交换myArray的两个元素N次和T个循环数。这个程序做它应该做的事情,但是在点击“返回0”之后,它显示了"program.exe已经停止工作“的错误信息。调试输出显示

代码语言:javascript
复制
Stack cookie instrumentation code detected a stack-based buffer overrun

为什么程序在其工作完成后显示错误?我怎么才能解决这个问题?

代码语言:javascript
复制
#include <iostream>
#include <ctime>    
#include <cstdlib>

using namespace std;

int main()
{
    const int N = 10000;
    const int T = 100; 

    srand((unsigned)time(0));   

    bool myArray[N] ;
    bool temp = true;
    int save1 = 0;
    int save2 = 0;

    //initializing myArray
    for (int index = 0; index < N/2; index++) {
        myArray[index] = false;
    }
    for (int index = N/2; index < N; index++) {
        myArray[index] = true;
    }

    for (int index = 0; index < T; index++) {

        for (int index1 = 0; index1 < N; index1++) {    
            save1 = int( N*rand()/RAND_MAX );
            save2 = int( N*rand()/RAND_MAX );


            temp = myArray[save1];
            myArray[save1] = myArray[save2] ;
            myArray[save2] = temp; 
        }
    }

    cout<<" Press any key to exit...";
    cin.get();

    return 0;
}

编辑:我必须生成从0到(N-1)的随机整数。在myArray中调用Nth位置会造成问题。

但以下两种方法都不一致地生成随机整数。

代码语言:javascript
复制
    save1 = int( (N-1)*rand()/RAND_MAX );

nor

代码语言:javascript
复制
    save1 = int( N*rand()/(RAND_MAX+1) );

关于这个方法的问题,有一个很好的视频。正如Mic和Bob__所指出的那样,也存在着由(N-1)*rand()引起的超支问题。

对于大范围的随机整数,这种模块化方法也是非常低效率的(请查看此文章以获得详细信息)。因此,我生成均匀随机数的最佳机会是以下方法(借用自本文)。

代码语言:javascript
复制
while(true)
{
  int value = rand();
  if (value < RAND_MAX - RAND_MAX % range)
    return value % range;
}

另外,对于改组数组元素,最好使用random_shuffle函数或Fisher–Yates shuffle来实现最佳性能。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-07-02 14:27:47

让我们考虑这一行(编辑的qustion):

代码语言:javascript
复制
save1 = int( (N-1)*rand()/RAND_MAX );

其中save1int类型的变量,N是相同类型的const,rand()返回0范围内的int,RAND_MAX。

在C++中,这个表达式是从左到右计算的,所以首先是乘法,然后是除法。如果rand()返回的值大于INT_MAX /(N-1),则此操作会溢出,导致未定义的行为。在大多数实现中,由于两种形式对积分值的补表示,结果可能是负值。

在此之后,执行RAND_MAX整数除法,以便对于任何值x,如-RAND_MAX

您可以看到这里编译和执行您的程序(我只添加了一行以证明我的观点)。请注意有多少次识别码不是零。

在C中,使用rand()生成0到N(排除在外)之间的随机数的一种常见方法是:

代码语言:javascript
复制
int number = rand() % N;

还可以考虑一个更好的算法来洗牌数组,比如费希尔·耶茨,您可以在C中实现该算法,如:

代码语言:javascript
复制
void my_c_shuffle(bool *arr, size_t n)
{
    while ( n > 1 )
    {
        size_t choice = rand() % n;
        --n;
        bool temp = arr[n];
        arr[n] = arr[choice];
        arr[choice] = temp;
    }
}

在C++中,您应该使用标准库而不是重写这些算法:

代码语言:javascript
复制
#include <iostream>
#include <random>
#include <array>
#include <algorithm>

int main()
{
    std::random_device rd;
    std::mt19937 g(rd());

    std::array<bool, 10000> my_array;
    auto middle = my_array.begin() + my_array.size() / 2;
    std::fill(my_array.begin(), middle, false);
    std::fill(middle, my_array.end(), true);

    std::shuffle(my_array.begin(), my_array.end(), g);  
}
票数 0
EN

Stack Overflow用户

发布于 2017-07-02 08:01:20

至少有一件事需要解决:

rand()返回0和RAND_MAX包含的随机整数,因此必须替换

代码语言:javascript
复制
  N*rand()/RAND_MAX 

通过

代码语言:javascript
复制
  N*rand()/(1+RAND_MAX)
票数 0
EN

Stack Overflow用户

发布于 2017-07-02 08:22:21

您应该将N替换为(N-1)。也许这就是你想要做的。

代码语言:javascript
复制
    save1 = int( (N-1)*rand()/RAND_MAX );
    save2 = int( (N-1)*rand()/RAND_MAX );

只是想知道您是否打算在语句中使用“Index1”来计算save1和save2。这也会解决问题。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44868543

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档