C++指针数组报Stack around the variable was corrupted错误排查
问题根因
你对C++表达式求值顺序的认知存在偏差,代码触发了数组越界写入,最终导致栈内存损坏。
- 先梳理代码中i的变化逻辑:白兵初始化循环的终止条件是
i < 56,循环结束后i的值固定为56。后续8行白方后排棋子的初始化语句,如果i正常逐行自增1,执行到最后一行时i的初始值是63,刚好是m_Board数组(合法索引范围0~63)的最后一个有效位置。 - 你对后置自增
i++的理解只对了一半:后置自增确实会返回i自增前的原值,但C++标准从未保证赋值号=两边的操作数一定从左到右求值:- C++17版本之前,赋值运算符左右两侧的求值顺序完全是未指定的,编译器可以先算左边的数组索引
m_Board[i],再算右边的new Rook(i++, 0);也可以先算右边的构造逻辑,执行i++把i从63改成64,再回头算左边的数组索引,这时候访问的就是非法地址m_Board[64],写入操作直接踩中栈上chess_board变量相邻的保护内存,就触发了你看到的"Stack around the variable 'chess_board' was corrupted"报错。 - 哪怕是C++17及之后的版本明确了"赋值操作先算右操作数、再算左操作数、最后赋值"的规则,你这种写法依然是错的:右操作数先执行
i++把i变成64,左操作数取索引的时候拿到的就是64,依然会越界。
- C++17版本之前,赋值运算符左右两侧的求值顺序完全是未指定的,编译器可以先算左边的数组索引
- 前面黑方后排初始化的8行一模一样的写法没报错,纯粹是运气:当时i的数值小,就算出现顺序偏差,越界写入的位置还没踩到栈的保护标记,没有触发显性错误,但从第一行初始化开始代码就已经存在不可靠的未定义行为了。
修复方案
绝对不要在同一个表达式中,既把变量作为数组索引/函数参数使用,又对变量做自增修改,彻底规避求值顺序带来的不可预期结果,把自增逻辑显式拆分即可:
//White pieces m_Board[i] = new Rook(i, 0); i++; m_Board[i] = new Knight(i, 0); i++; m_Board[i] = new Bishop(i, 0); i++; m_Board[i] = new Queen(i, 0); i++; m_Board[i] = new King(i, 0); i++; m_Board[i] = new Bishop(i, 0); i++; m_Board[i] = new Knight(i, 0); i++; m_Board[i] = new Rook(i, 0); i++;
这种写法逻辑完全明确,不存在任何歧义,也不会触发越界问题。
内容的提问来源于stack exchange,提问作者Dương Thiên Bảo
相关产品推荐
相关产品推荐

