在 C++ 中对 STL 列表使用 push_back()导致访问冲突、崩溃
我正在使用自己的自制游戏引擎创建游戏,但在使用列表时遇到了麻烦。
我的程序中有一个名为 BoardState 的结构。这些结构中的每一个都有一个称为子项的 BoardState 指针列表。这是因为我为游戏的 AI 创建了一棵 BoardStates 树。
为了帮助创建我的树,我有一个名为 MakeBoard 的函数。该函数获取创建新板所需的所有信息,然后它将指向该新板的指针添加到父板子列表的末尾。这是相关的函数 MakeBoard:
void MakeBoard(BoardState* pStartBoard, int iPiece, int iPosStart, int iPosFinish, int* pJumpArray)
{
//BoardState* pNewBoard = &NewBoard;
//pNewBoard->bPlayerTurn = !(pStartBoard->bPlayerTurn);
//NewBoard.bPlayerTurn = !(pStartBoard->bPlayerTurn);
BoardState* pNewBoard = (BoardState*)malloc(sizeof(BoardState));
pNewBoard->bPlayerTurn = !(pStartBoard->bPlayerTurn);
// Copy the BoardPositions of the starting board into the new Board.
for(int i = 0; i < 37; i++)
{
pNewBoard->posArray[i] = pStartBoard->posArray[i];
//NewBoard.posArray[i] = pStartBoard->posArray[i];
}
// Make the BoardPosition change necessary to reflect the move.
pNewBoard->posArray[iPosStart] = -1;
pNewBoard->posArray[iPosFinish] = iPiece;
//NewBoard.posArray[iPosStart] = -1;
//NewBoard.posArray[iPosFinish] = iPiece;
// Now account for any pieces that were jumped, if applicable.
if(pJumpArray != NULL)
{
for(int i = 0; i < 16; i++)
{
if(pJumpArray[i] != -1)
{
pNewBoard->posArray[pJumpArray[i]] = -1;
//NewBoard.posArray[pJumpArray[i]] = -1;
}
}
}
// Connect the parent board to this child board.
pNewBoard->parent = pStartBoard;
//NewBoard.parent = pStartBoard;
//pStartBoard->children.push_back(_pTestState);
pStartBoard->children.push_back(pNewBoard); // <- The problem
//pStartBoard->children.push_back(&NewBoard);
}
额外的注释部分是我尝试其他想法以查看它们是否有效的地方。
不幸的是,这会导致程序抛出以下错误:
访问冲突读取位置 0xcdcdcdd1。
如果我深入调试器,我发现问题发生在 STL 列表文件中。这些是调用堆栈中的前三个调用:
<块引用>OpenGL_Engine_Test1.exe!std::list >::_Insert(std::list >::_Const_iterator<1> _Where=..., tagBoardState * const & _Val=0x049a1a80) 第 718 行 + 0x10 字节 C++
OpenGL_Engine_Test1.exe!std::list<tagBoardState *,std::allocator<tagBoardState *> >::push_back(tagBoardState * const & _Val=0x049a1a80) Line 670 + 0x51 bytes C++
OpenGL_Engine_Test1.exe!MakeBoard(tagBoardState * pStartBoard=0x049a0580, int iPiece=16, int iPosStart=21, int iPosFinish=16, int * pJumpArray=0x00000000) Line 352 C++
然后打开查找定义list的文件,并指出_insert中的问题行 功能:
void _Insert(const_iterator _Where, const _Ty& _瓦尔) { // 在 _Where 处插入 _Val
#if _HAS_ITERATOR_DEBUGGING if (_Where._Mycont != this) _DEBUG_ERROR("列表插入迭代器超出范围"); #endif /* _HAS_ITERATOR_DEBUGGING */
_Nodeptr _Pnode = _Where._Mynode();
_Nodeptr _Newnode = _Buynode(_Pnode, _Prevnode(_Pnode), _Val); // PROBLEM
_Incsize(1);
_Prevnode(_Pnode) = _Newnode;
_Nextnode(_Prevnode(_Newnode)) = _Newnode;
}
除此之外,我真的不知道更多了。我不知道为什么会出现这个问题。我知道“访问冲突”基本上意味着我要么试图访问不存在的东西,我无权访问,要么存在某种范围问题,但我看不出有什么问题其中适用。
如果有人能指出我正确的方向,我将非常感激。我做了很多搜索,但几乎我发现的所有内容都与向量有关,而且似乎并不是我的问题。
I'm creating a game using my own homemade gaming engine, but I'm running into trouble using lists.
I have a structure in my program called BoardState. Each of these structures has a list of BoardState pointers called children. This is because I create a tree of BoardStates for the AI of my game.
To aid in the creation of my tree, I have a function called MakeBoard. This function gets passed all the information it needs to create a new board, and then it should add the pointer to that new board to the end of the parent board's children list. Here is the relevant function, MakeBoard:
void MakeBoard(BoardState* pStartBoard, int iPiece, int iPosStart, int iPosFinish, int* pJumpArray)
{
//BoardState* pNewBoard = &NewBoard;
//pNewBoard->bPlayerTurn = !(pStartBoard->bPlayerTurn);
//NewBoard.bPlayerTurn = !(pStartBoard->bPlayerTurn);
BoardState* pNewBoard = (BoardState*)malloc(sizeof(BoardState));
pNewBoard->bPlayerTurn = !(pStartBoard->bPlayerTurn);
// Copy the BoardPositions of the starting board into the new Board.
for(int i = 0; i < 37; i++)
{
pNewBoard->posArray[i] = pStartBoard->posArray[i];
//NewBoard.posArray[i] = pStartBoard->posArray[i];
}
// Make the BoardPosition change necessary to reflect the move.
pNewBoard->posArray[iPosStart] = -1;
pNewBoard->posArray[iPosFinish] = iPiece;
//NewBoard.posArray[iPosStart] = -1;
//NewBoard.posArray[iPosFinish] = iPiece;
// Now account for any pieces that were jumped, if applicable.
if(pJumpArray != NULL)
{
for(int i = 0; i < 16; i++)
{
if(pJumpArray[i] != -1)
{
pNewBoard->posArray[pJumpArray[i]] = -1;
//NewBoard.posArray[pJumpArray[i]] = -1;
}
}
}
// Connect the parent board to this child board.
pNewBoard->parent = pStartBoard;
//NewBoard.parent = pStartBoard;
//pStartBoard->children.push_back(_pTestState);
pStartBoard->children.push_back(pNewBoard); // <- The problem
//pStartBoard->children.push_back(&NewBoard);
}
The extra commented parts are where I was trying out other ideas to see if they worked.
Unfortunately this causes the program to throw the following error:
Access violation reading location 0xcdcdcdd1.
If I dig into the debugger, I find out that the problem is occurring in the STL list file. These are the top three calls in the call stack:
OpenGL_Engine_Test1.exe!std::list >::_Insert(std::list >::_Const_iterator<1> _Where=..., tagBoardState * const & _Val=0x049a1a80) Line 718 + 0x10 bytes C++
OpenGL_Engine_Test1.exe!std::list<tagBoardState *,std::allocator<tagBoardState *> >::push_back(tagBoardState * const & _Val=0x049a1a80) Line 670 + 0x51 bytes C++
OpenGL_Engine_Test1.exe!MakeBoard(tagBoardState * pStartBoard=0x049a0580, int iPiece=16, int iPosStart=21, int iPosFinish=16, int * pJumpArray=0x00000000) Line 352 C++
It then opens up the file where list is defined, and points out the problem line inside the _insert function:
void _Insert(const_iterator _Where,
const _Ty& _Val)
{ // insert _Val at _Where
#if _HAS_ITERATOR_DEBUGGING
if (_Where._Mycont != this)
_DEBUG_ERROR("list insert iterator outside range");
#endif /* _HAS_ITERATOR_DEBUGGING */
_Nodeptr _Pnode = _Where._Mynode();
_Nodeptr _Newnode = _Buynode(_Pnode, _Prevnode(_Pnode), _Val); // PROBLEM
_Incsize(1);
_Prevnode(_Pnode) = _Newnode;
_Nextnode(_Prevnode(_Newnode)) = _Newnode;
}
Beyond this, i don't really know more. I have no idea why this problem is occurring. I know that an "Access Violation" basically means that I'm either trying to access something that doesn't exist, I don't have access to, or there is some sort of scope problem, but I can't see how any of those are applicable.
If anyone can point me in the right direction, I would really appreciate it. I've done a lot of searching, but almost everything I've found has been pertaining to Vectors and haven't seemed to be my issue exactly.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果您对 C++ 类进行 malloc(),则不会为该类的任何字段调用构造函数,包括您的问题向量。你需要使用新的。
我假设 pStartBoard 的分配与 pNewBoard 相同,但即使情况并非如此,您也会在 pNewBoard 中遇到相同的问题。
If you malloc() a C++ class, no constructors will be called for any of that class's fields, including your problem vector. You need to use new.
I've made an assumption that pStartBoard was allocated the same as pNewBoard, but you will have the same problem in pNewBoard even if this is not the case.
读取位置 0xcdcdcdd1 时出现访问冲突。表示单位化变量。调试器将这样的值作为标记放入。不幸的是,我无法推断出您在哪里看到错误,也无法推断出代码示例中的任何 STL 容器。但“pNewBoard->posArray”将是我首先查看的地方。该类的构造函数是否将该成员设置为某些内容?
Access violation reading location 0xcdcdcdd1. Indicates an unitialized variable. The debugger puts in values like that as markers. Unfortunately, I can't deduce where you are seeing the error, nor any STL containers in your code sample. But 'pNewBoard->posArray' would be the first place I look. Does that class's constructor set that member to something?