C++ 在结构体中使用Vector容器可能发生的段错误问题

今天,在写A*寻路算法的过程中,遇到了一个段错误,花了好久才搞定,特此记录。

问题描述

涉及到的关键代码主要有两个部分:

1、搜索树结构体的定义中,加入了Vector<TreeNode*> pChildren容器用于储存孩子结点的地址

//A*搜索树结构
struct TreeNode 
{
    Pos MyPos;                          //位置信息
    TreeNode* pParent = nullptr;        //父结点指针
    vector<TreeNode*> pChildren;        //孩子结点指针
};

2、在主函数的某一循环体中,使用push_back()函数给pChildren容器添加元素

for (int i = 0; i < 8; i++)
{
    ……
    if(……)
    {
        //创建新结点
        pNew = CreateTreeNode(TempPos);
        //结点设置为pTempNode的子结点
        pTempNode->pChildren.push_back(pNew);
        ……
    }
}

程序运行异常:pTempNode->pChildren.push_back(pNew);  容器每次在添加第6个元素时就会发生段错误,程序中断。

原因分析

先说结论:该段错误是由于当前Vector容器大小已达到容器容量上限,再次给容器添加元素导致内存空间不足,从而触发段错误。

1、当一个Vector容器被定义时,系统会给Vector分配一定的内存空间(Capacity),当Vector中元素不断增加至将要超过该容量时,

系统会分配一个更大的内存空间,在将之前的元素复制到新空间中,在新空间中继续添加元素。

2、结构体的数据成员是储存在一段连续的内存空间中的,且该空间大小通常是无法改变的。

当Vector被定义在结构体中时,遇到容量不足的情况,无法开辟新内存空间以存储新元素,便会导致内存不足,程序中断。

解决办法

我目前只想到了一个比较笨的方法,放弃在结构体中使用Vector,改为定义多个指针。

相关代码修改如下:

//A*搜索树结构
struct TreeNode
{
    Pos MyPos;                          //位置信息
    TreeNode* pParent = nullptr;        //父结点指针
    TreeNode* pChild0 = nullptr;        //孩子0结点指针
    TreeNode* pChild1 = nullptr;        //孩子1结点指针
    TreeNode* pChild2 = nullptr;        //孩子2结点指针
    TreeNode* pChild3 = nullptr;        //孩子3结点指针
    TreeNode* pChild4 = nullptr;        //孩子4结点指针
    TreeNode* pChild5 = nullptr;        //孩子5结点指针
    TreeNode* pChild6 = nullptr;        //孩子6结点指针
    TreeNode* pChild7 = nullptr;        //孩子7结点指针
};
for (int i = 0; i < 8; i++)
{
    ……
    if(……)
    {
        //创建新结点
        pNew = CreateTreeNode(TempPos);
        //结点设置为pTempNode的子结点
        switch (i)
        {
        case 0:     pTempNode->pChild0 = pNew;   break;
        case 1:     pTempNode->pChild1 = pNew;   break;
        case 2:     pTempNode->pChild2 = pNew;   break;
        case 3:     pTempNode->pChild3 = pNew;   break;
        case 4:     pTempNode->pChild4 = pNew;   break;
        case 5:     pTempNode->pChild5 = pNew;   break;
        case 6:     pTempNode->pChild6 = pNew;   break;
        case 7:     pTempNode->pChild7 = pNew;   break;
        default:     break;
        }
    }
}

 


版权声明:本文为weixin_44928892原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。