gpt4 book ai didi

使用递归函数时的 C++ 堆栈溢出

转载 作者:行者123 更新时间:2023-11-30 04:06:45 24 4
gpt4 key购买 nike

我有一个具有递归函数的类。我测试了 100 个案例,代码运行良好。然而,我运行了另一个测试,在几次递归调用之后,收到了一个显示堆栈溢出的第一次机会异常,我选择忽略它,然后显示一个关于内存读取违规的未处理异常。

假设我有以下代码(不是真正的代码,它有退出条件):

class Foo {
void Bar () {
Bar();
};
};

当我使用调试器时,我发现在调用Bar 时,this 指针接收到错误的地址号,导致读取Foo 对象错误,我不知道为什么。

有人知道吗?

还是我应该试试?

class Foo {
static void Bar (Foo* obj) {
Foo::Bar(obj);
};
};

编辑

这是用于模拟游戏 Jewel 的真实代码。我在 scanTile 方法中发现了问题

enum MOVE {MOVE_T, MOVE_L, MOVE_R, MOVE_B}; // Move Direction
enum SCORE {SCORE_3 = 1, SCORE_4 = 2, SCORE_5 = 4}; // Score Types
enum ERROR {ERR_DROP = 1, ERR_COUNT, ERR_MOVE}; // User-defined Error Code

class Jewel {
private:
UINT32 m, n, score, x, y;
char** map;
bool** scanned;
char move;

void init () {
map = new char*[n];
scanned = new bool*[n];
for (UINT32 i = 0; i < n; i++) {
map[i] = new char[m];
scanned[i] = new bool[n];
};
};

void reinit () {
for (UINT32 i = 0; i < n; i++)
for (UINT32 j = 0; j < n; j++)
scanned[i][j] = false;
};

void uninit () {
for (UINT32 i = 0; i < n; i++) {
delete[m] map[i];
delete[n] scanned[i];
};

delete[n] map;
delete[n] scanned;
};

void fileInput () {
std::ifstream fInput("input.txt");
fInput >> n >> m;

init();

for (UINT32 j = 0; j < m; j++)
for (UINT32 i = 0; i < n; i++)
fInput >> map[i][j];

fInput.close();
};

void fileOutput () {
std::ofstream fOutput("output.txt");
fOutput << score << '\n';

for (UINT32 j = 0; j < n; j++) {
for (UINT32 i = 0; i < n; i++)
fOutput << map[i][n - 1 - j] << ' ';
fOutput << '\n';
};

fOutput.close();

uninit();
};

bool inputMove () {
std::cin >> x >> y >> move;
if ((x == -1) && (y == -1) && (move == 'A'))
return false;
else
return true;
};

void outputMove () {
std::cout << '\n' << score << '\n';

for (UINT32 j = 0; j < n; j++) {
for (UINT32 i = 0; i < n; i++) {
std::cout << map[i][n - 1 - j] << ' ';
};

std::cout << '\n';
};
};

void swap(char &a, char &b) {
char temp = a;
a = b;
b = temp;
};

bool beginMove () {
switch (move) {
case 'T':
if (x < n - 1) {
swap(map[y][x], map[y][x + 1]);
return true;
};
break;
case 'B':
if (0 < x) {
swap(map[y][x], map[y][x - 1]);
return true;
};
break;
case 'L':
if (0 < y) {
swap(map[y][x], map[y - 1][x]);
return true;
};
break;
case 'R':
if (y < n - 1) {
swap(map[y][x], map[y + 1][x]);
return true;
};
break;
};

return false;
};

void revertMove () {
switch (move) {
case 'T':
swap(map[y][x], map[y][x + 1]);
break;
case 'B':
swap(map[y][x], map[y][x - 1]);
break;
case 'L':
swap(map[y][x], map[y - 1][x]);
break;
case 'R':
swap(map[y][x], map[y + 1][x]);
break;
};
};

void drop () {
for (UINT32 i = 0; i < n; i++) {
UINT32 j = 0;

while (j < n && map[i][j])
j++;

if (j < n) {
UINT32 k = j + 1;

while (j < n)
if (!map[i][j]) {
while ((k < m) && !map[i][k])
k++;

if (!map[i][k])
exit(ERR_DROP);

map[i][j] = map[i][k];
map[i][k] = 0;

j++;
k++;
};
};
};
};

bool scanMap () {
reinit();
UINT32 sessionScore = 0;

for (UINT32 j = 0; j < n; j++)
for (UINT32 i = 0; i < n; i++)
if (!scanned[i][j])
sessionScore += startScan(i, j);

if (sessionScore) {
score += sessionScore;
return true;
} else
return false;
};

UINT32 startScan(const UINT32 &col, const UINT32 &row) {
UINT32 count = 1;
scanned[col][row] = true;

if ((row < n - 1) && !scanned[col][row + 1] && (map[col][row] == map[col][row + 1]))
count += scanTile(col, row + 1, MOVE_T, (0 < row) && (map[col][row] == map[col][row - 1]));

if ((0 < row) && !scanned[col][row - 1] && (map[col][row] == map[col][row - 1]))
count += scanTile(col, row - 1, MOVE_B, (row < n - 1) && (map[col][row] == map[col][row + 1]));

if ((col < n - 1) && !scanned[col + 1][row] && (map[col][row] == map[col + 1][row]))
count += scanTile(col + 1, row, MOVE_R, (0 < col) && (map[col][row] == map[col - 1][row]));

if ((0 < col) && !scanned[col - 1][row] && (map[col][row] == map[col - 1][row]))
count += scanTile(col - 1, row, MOVE_L, (col < n - 1) && (map[col][row] == map[col + 1][row]));

if ((count < 3) && (count != 1))
exit(ERR_COUNT);

if (count >= 3)
map[col][row] = 0;

if (count == 1)
return 0;
else if (count == 3)
return count*SCORE_3;
else if (count == 4)
return count*SCORE_4;
else if (count >= 5)
return count*SCORE_5;
};

UINT32 scanTile(const UINT32 &col, const UINT32 &row, const MOVE &direction, const bool &opposite = false) {
UINT32 count = 1;
UINT32 temp = 0;
bool counted = false;

switch (direction) {
case MOVE_T:
if ((row < n - 1) && (map[col][row] == map[col][row + 1]))
if (scanned[col][row + 1])
counted = true;
else
count += scanTile(col, row + 1, MOVE_T, (0 < row) && (map[col][row] == map[col][row - 1]));
break;
case MOVE_B:
if ((0 < row) && (map[col][row] == map[col][row - 1]))
if (scanned[col][row - 1])
counted = true;
else
count += scanTile(col, row - 1, MOVE_B, (row < n - 1) && (map[col][row] == map[col][row + 1]));
break;
case MOVE_R:
if ((col < n - 1) && (map[col][row] == map[col + 1][row]))
if (scanned[col + 1][row])
counted = true;
else
count += scanTile(col + 1, row, MOVE_R, (0 < col) && (map[col][row] == map[col - 1][row]));
break;
case MOVE_L:
if ((0 < col) && (map[col][row] == map[col - 1][row]))
if (scanned[col - 1][row])
counted = true;
else
count += scanTile(col - 1, row, MOVE_L, (col < n - 1) && (map[col][row] == map[col + 1][row]));
break;
default:
exit(ERR_MOVE);
};

if ((opposite ? 1 : 0) + 1 + count + (counted ? 1 : 0) >= 3) {
switch (direction) {
case MOVE_T:
case MOVE_B:
temp = 0;
if ((col < n - 1) && !scanned[col + 1][row] && (map[col][row] == map[col + 1][row]))
count += temp = scanTile(col + 1, row, MOVE_R, (0 < col) && (map[col][row] == map[col - 1][row]));
if ((0 < col) && !scanned[col - 1][row] && (map[col][row] == map[col - 1][row]))
count += scanTile(col - 1, row, MOVE_L, temp ? true : false);
break;
case MOVE_L:
case MOVE_R:
temp = 0;
if ((row < n - 1) && !scanned[col][row + 1] && (map[col][row] == map[col][row + 1]))
count += temp = scanTile(col, row + 1, MOVE_T, (0 < row) && (map[col][row] == map[col][row - 1]));
if ((0 < row) && !scanned[col][row - 1] && (map[col][row] == map[col][row - 1]))
count += scanTile(col, row - 1, MOVE_B, temp ? true : false);
break;
default:
exit(ERR_MOVE);
};

scanned[col][row] = true;
map[col][row] = 0;
return count;
} else {
return 0;
};
};

public:
Jewel () : score(0) {
fileInput();
};

void process () {
outputMove();

while (inputMove()) {
if (beginMove()) {
bool first = true;

while (scanMap()) {
outputMove();
drop();
outputMove();
first = false;
};

if (first)
revertMove();
};

outputMove();
};

fileOutput();
};
};

最佳答案

与许多其他东西一样,堆栈是大小有限的东西,随着递归,您使用的空间越来越多,直到用完并且程序溢出。

在基于 *nix 的操作系统下,通常您可以使用命令 ulimit -aulimit -s(较短的输出)来获取堆栈的大小,在 a GNU/linux 发行版通常约为 7/8Mb。

关于使用递归函数时的 C++ 堆栈溢出,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22787678/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com