Переполнение стека / ошибка сегмента при работе со случайными числами - PullRequest
1 голос
/ 18 февраля 2012

Я создаю небольшую игру в крестики-нолики и генерирую движение компьютера случайным образом, используя эту функцию:

//Generates the computer's move randomly
void tictactoe::getComputerMove( char** b )
{
    int rand1,rand2;

    //Generate two random numbers
    rand1 = rand() % 2;//0-2
    rand2 = rand() % 2;//0-2

    //Check if that spot is taken yet.
    if( b[rand1][rand2] == ' ' )//Empty
            b[rand1][rand2] = 'O';

    else //Already filled.
        getComputerMove( b );
}

Эта функция вызывается в цикле сразу после того, как пользователь сделал свой ход. Причина, по которой я думаю, что это проблема, заключается в том, что сообщение, которое я получаю, касается случайностей, и это единственное место, где я их использую. У меня есть эти файлы в комплекте:

#include "tictactoe.h" //Homemade header file
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string>
#include <iostream>

Сообщение об ошибке, сгенерированное valgrind, выглядит так:

==31280== Stack overflow in thread 1: can't grow stack to 0xbe398ff8
==31280== 
==31280== Process terminating with default action of signal 11 (SIGSEGV)
==31280==  Access not within mapped region at address 0xBE398FF8
==31280==    at 0x41AB4BF: random_r (random_r.c:364)
==31280==  If you believe this happened as a result of a stack
==31280==  overflow in your program's main thread (unlikely but
==31280==  possible), you can try to increase the size of the
==31280==  main thread stack using the --main-stacksize= flag.
==31280==  The main thread stack size used in this run was 8388608.
==31280== Stack overflow in thread 1: can't grow stack to 0xbe398ff4
==31280== 
==31280== Process terminating with default action of signal 11 (SIGSEGV)
==31280==  Access not within mapped region at address 0xBE398FF4
==31280==    at 0x4021430: _vgnU_freeres (vg_preloaded.c:58)
==31280==  If you believe this happened as a result of a stack
==31280==  overflow in your program's main thread (unlikely but
==31280==  possible), you can try to increase the size of the
==31280==  main thread stack using the --main-stacksize= flag.
==31280==  The main thread stack size used in this run was 8388608.
==31280== 
==31280== HEAP SUMMARY:
==31280==     in use at exit: 21 bytes in 4 blocks
==31280==   total heap usage: 4 allocs, 0 frees, 21 bytes allocated
==31280== 
==31280== LEAK SUMMARY:
==31280==    definitely lost: 0 bytes in 0 blocks
==31280==    indirectly lost: 0 bytes in 0 blocks
==31280==      possibly lost: 0 bytes in 0 blocks
==31280==    still reachable: 21 bytes in 4 blocks
==31280==         suppressed: 0 bytes in 0 blocks
==31280== Rerun with --leak-check=full to see details of leaked memory
==31280== 
==31280== For counts of detected and suppressed errors, rerun with: -v
==31280== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 20 from 9)
Segmentation fault

Код для создания массива 2d:

char ** tictactoe :: createBoard () { // Инициализируем что-то символ ** доска;

    //Allocate memory for the array
    board = new char* [3];

    for( int i = 0; i < 3; i++ )
    {
        board[i] = new char[3];
    }

    //Now fill each slot with a dummy ' '
    for( int i = 0; i < 3; i++ )
    {
        for( int j = 0; j < 3; j++ )
            board[i][j] = ' ';
    }

    return board;
}

Ответы [ 2 ]

2 голосов
/ 18 февраля 2012

Операция вашего мода rand() % 2 будет выводить только 0 или 1, вы должны использовать rand() % 3. Вероятно, происходит то, что вы только случайно изучаете подматрицу 2x2 всей доски.

1 голос
/ 18 февраля 2012

Причина, по которой я думаю, что это проблема, заключается в том, что сообщение, которое я получаю, касается случайностей

Нет. Он просто падает, когда доска (а точнее: верхняя часть 2x2, так как %2 будет выводить только 0 и 1) заполнена: в этом случае нет условий выхода. Вместо этого вы вызываете getComputerMove(), пока стек не заполнится: переполнение стека.

...