简体   繁体   English

数组的重排元素:基于堆栈的缓冲区溢出错误

[英]Shuffling elements of Array : stack-based buffer overrun error

My given code is the problem part of the original program. 我给定的代码是原始程序的问题部分。 It swaps two elements of myArray randomly N times and in T number of loops. 它将N次随机交换myArray的两个元素,并进行T次循环。 The program does what it is supposed to but after hitting "return 0" it shows error massage of "program.exe has stopped working". 该程序执行了预期的操作,但是在单击“返回0”后,它显示错误消息“ program.exe已停止工作”。 The debug output shows 调试输出显示

Stack cookie instrumentation code detected a stack-based buffer overrun

Why the program is showing error after its job is done? 为什么程序在完成工作后显示错误? How can I fix this ? 我怎样才能解决这个问题 ?

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

EDIT: I had to generate random integer from 0 to (N-1). 编辑:我必须生成从0到(N-1)的随机整数。 Calling Nth location in myArray was creating the problem. 在myArray中调用第N个位置会导致问题。

But neither of the following methods generates random integer uniformly. 但是以下两种方法均不能统一生成随机整数。

    save1 = int( (N-1)*rand()/RAND_MAX );

nor 也不

    save1 = int( N*rand()/(RAND_MAX+1) );

There is a nice video on the problem of this method. 关于此方法的问题,有一个很好的视频 There is also the problem of overrun caused by (N-1)*rand() as Mic and Bob__ pointed out. 正如Mic和Bob__指出的那样,还有(N-1)*rand()引起的超限问题。

This modulo method is also very inefficient for large range of random integer (check this article for details). 对于较大范围的随机整数,这种取模方法也非常无效(请查看本文以了解详细信息)。 So, my best chance of generating uniform random numbers is the following method (borrowed from the article). 因此,生成统一随机数的最佳机会是以下方法(从本文中借用)。

while(true)
{
  int value = rand();
  if (value < RAND_MAX - RAND_MAX % range)
    return value % range;
}

Also for shuffling array elements it is best to use random_shuffle function or Fisher–Yates shuffle for optimum performance. 同样对于混洗数组元素,最好使用random_shuffle函数或Fisher–Yates shuffle以获得最佳性能。

At least one thing to fix: 至少要解决的一件事:

rand() returns a random integer between 0 and RAND_MAX inclusive, thus you must replace rand()返回介于0和RAND_MAX(含)之间的随机整数,因此您必须替换

  N*rand()/RAND_MAX 

by 通过

  N*rand()/(1+RAND_MAX)

You should replace N with (N-1) . 您应将N替换为(N-1) Probably that's what you want to do. 大概就是您想要的。

    save1 = int( (N-1)*rand()/RAND_MAX );
    save2 = int( (N-1)*rand()/RAND_MAX );

Just wondering if your intention is to use `Index1' in statements to calculate save1 & save2. 只是想知道您是否打算在语句中使用“ Index1”来计算save1和save2。 That will fix issue too. 那也将解决问题。

Let's consider this line (of the edited qustion): 让我们考虑一下(已编辑的问题的)这一行:

save1 = int( (N-1)*rand()/RAND_MAX );

Where save1 is a variable of type int , N is a const of the same type and rand() returns an int in the range [0, RAND_MAX]. 其中save1int类型的变量, N是相同类型的const,而rand()返回范围为[0,RAND_MAX]的int

In C++ this expression is evaluated left to right, so first the multiplication, then the division. 在C ++中,此表达式是从左到右求值的,因此首先是乘法,然后是除法。 If rand() returns a value greater then INT_MAX / (N - 1), this operation overflows causing Undefined Behavior. 如果rand()返回的值大于INT_MAX /(N-1),则此操作溢出,导致未定义行为。 In most implementations, due to two's complement representation of integral values, the result can be a negative value. 在大多数实现中,由于整数值的二进制补码表示,结果可能是负值。

After that, an integer division by RAND_MAX is performed, so that for any value x such that -RAND_MAX < x < RAND_MAX the result is 0. 之后,执行RAND_MAX的整数除法,以便对于-RAND_MAX <x <RAND_MAX的任何值x,结果均为0。

You can see here that your program (I only added a line to prove my point) compiles and executes. 您可以在此处看到您的程序(我只添加了一行来证明我的观点)已编译并执行。 Please note how many times the indeces are not zero. 请注意,索引的次数不为零。

A common way in C, using rand() , to generate a random number between 0 and N (excluded) is: 在C中,使用rand()生成介于0和N之间的随机数(不包括在内)的常见方法是:

int number = rand() % N;

Consider also a better algorithm to shuffle an array, like Fisher Yates , that you could implement in C as: 还要考虑一种更好的算法来对数组进行混洗,例如Fisher Yates ,您可以在C语言中实现为:

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

In C++ you should use the Standard Library instead of rewriting those algorithms: 在C ++中,您应该使用标准库而不是重写这些算法:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 0x00363A09处未处理的异常,堆栈cookie工具代码检测到基于堆栈的缓冲区溢出 - Unhandled exception at 0x00363A09, Stack cookie instrumentation code detected a stack-based buffer overrun 从头开始编写 heapify 函数,获得“基于堆栈的缓冲区溢出” - Writing heapify function from scratch, getting a “stack-based buffer overrun” 如何检测哪个变量/代码正在创建基于堆栈的缓冲区溢出 - How to detect which variable/code is creating a stack-based buffer overrun 为什么我的互操作代码会抛出“堆栈 cookie 检测代码检测到基于堆栈的缓冲区溢出”异常? - Why does my Interop code throw a "Stack cookie instrumentation code detected a stack-based buffer overrun" exception? 基于堆栈的回文检查器 - Stack-based palindrome checker 什么是基于堆栈的引用? - What is stack-based reference? 重新增长数组时出错:写入时缓冲区溢出 - Error while regrowing an array: Buffer overrun while writing to 带有LoadLibrary的STATUS_STACK_BUFFER_OVERRUN - STATUS_STACK_BUFFER_OVERRUN with LoadLibrary 如何在Windows上报告堆栈缓冲区溢出? - How to report a stack buffer overrun on Windows? 基于堆栈的迷宫算法背后的逻辑 - Logic behind a stack-based maze algorithm
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM