C++ 分割错误?

C++ 分割错误?,c++,c,artificial-intelligence,C++,C,Artificial Intelligence,我目前正在为学校做这个项目,在那里我正在实施一个算法来为“骑士游戏”找到一个解决方案(它是关于找到从棋盘左上角到右下角的最短路径),但我已经三天没有遇到这种分段错误,我检查了我用过的每一个指针,一切似乎都正常。 我实现了“搜索算法”,bfs、dfs和ucs,前两个很好,但ucs给了我分割错误,尽管它们使用的是相同的东西,除了popBest函数。 以下是ucs和popBest功能的一些图片: Item *popBest( list_t *list ) // and remove the best

我目前正在为学校做这个项目,在那里我正在实施一个算法来为“骑士游戏”找到一个解决方案(它是关于找到从棋盘左上角到右下角的最短路径),但我已经三天没有遇到这种分段错误,我检查了我用过的每一个指针,一切似乎都正常。 我实现了“搜索算法”,bfs、dfs和ucs,前两个很好,但ucs给了我分割错误,尽管它们使用的是相同的东西,除了popBest函数。 以下是ucs和popBest功能的一些图片:

Item *popBest( list_t *list ) // and remove the best board from the list.
{
  assert(list);
  assert(list->numElements);

  int min_f;

  Item *item = list->first;
  Item *best;
  min_f = list->first->f;

  while (item) {
    if (item->f < min_f) {
      min_f = item->f;
      best = item;
    }
    item = item->next;
  }
  //item = onList(list, board);
  delList(list, best);

  return best;
}

void ucs(void)
{
    Item *cur_node, *child_p, *temp;

    while ( listCount(&openList_p) ) { /* While items are on the open list 
        printLt(openList_p );
        /* Get the first item on the open list*/
        cur_node = popBest(&openList_p);
        //printf("%d  %f\n", listCount(&openList_p), evaluateBoard( cur_node ));
        printBoard(cur_node);

        addFirst(&closedList_p, cur_node);

        if ( evaluateBoard(cur_node) == 0.0 ) {
            showSolution(cur_node);
            printf("\nParcours en largeur (bfs)\n" );
            return;
       }
       else {
            for (int i = 0; i < MAX_BOARD; i++) {
                child_p = getChildBoard( cur_node, i );

                if (child_p != NULL) {
                    child_p->f = cur_node->f+1;
                    temp = onList(&openList_p, child_p->board);
                    if (temp ==NULL) addLast( &openList_p, temp);
                    else if (temp != NULL && child_p->f < temp->f )
                    {
                        delList(&openList_p, temp);
                        addLast( &openList_p, temp);
                    }
                  }
                }
            }
        }

    return;
}
Item*popBest(list\t*list)//并从列表中删除最佳线路板。
{
断言(列表);
断言(列表->数值);
国际货币基金组织;
项目*项目=列表->第一;
项目*最佳;
最小值=列表->第一个->f;
while(项目){
如果(项目->ff;
最佳=项目;
}
项目=项目->下一步;
}
//项目=在线列表(列表、板);
delList(列表,最佳);
回报最好;
}
无效ucs(无效)
{
项目*当前节点,*子节点,*温度;
while(listCount(&openList_p)){/*while项位于打开列表上
printLt(openList_p);
/*获取打开列表中的第一项*/
cur_node=popBest(&openList_p);
//printf(“%d%f\n”、listCount(&openList_p)、evaluateBoard(cur_节点));
印刷板(cur_节点);
addFirst(关闭列表和当前节点);
if(评估板(cur_节点)==0.0){
showSolution(当前节点);
printf(“\nParcures en largeur(bfs)\n”);
回来
}
否则{
对于(int i=0;if=当前节点->f+1;
temp=在线列表(&openList\u p,子\u p->board);
如果(temp==NULL)addLast(&openList\p,temp);
else if(temp!=NULL&&child\p->ff)
{
delList(和openList_p,temp);
addLast(和openList_p,temp);
}
}
}
}
}
回来
}

所有的函数都适用于bfs和dfs,唯一的区别是popBest函数。

您可以执行
list->first->f
,而不检查
list->first
是否为空指针

问题的原因可能是
best
在循环后可能未初始化,如果列表中的第一个元素是“best”,则肯定会出现此问题

这是一个更安全的版本

Item *popBest( list_t *list )
{
  assert(list);
  assert(list->numElements);
  assert(list->first);

  // Assume that the first element is best.
  Item *best = list->first;
  int min_f = best->f;

  // Search from the second element (if it exists).
  Item* item = best->next;
  while (item) {
    if (item->f < min_f) {
      min_f = item->f;
      best = item;
    }
    item = item->next;
  }
  delList(list, best);
  return best;
}
Item*popBest(列表)
{
断言(列表);
断言(列表->数值);
断言(列表->第一);
//假设第一个元素是最好的。
项目*最佳=列表->第一;
int min_f=最佳->f;
//从第二个元素(如果存在)进行搜索。
项目*项目=最佳->下一步;
while(项目){
如果(项目->ff;
最佳=项目;
}
项目=项目->下一步;
}
delList(列表,最佳);
回报最好;
}

请将您的代码引用转换为a。如果您做得正确,您可能会在途中找到答案。我几乎修复了错误的代码注释(与
/*
/
不匹配),但可能这是在您的实际代码中,因此您应该首先验证这一点,然后将实际代码粘贴到问题上(也要使其成为MCVE)。我会的,非常感谢。不,这不是我的,我想在写问题时编辑它,但在发布代码时我没有注意到。感谢测试是如果你运行你在这里发布的代码,并检查它是否再现了你的实际问题。如果你的真实代码在发布到这里之前需要一些编辑,那么在线编译器可以非常方便地创建mcve。例如,这里的代码没有编译(因此没有segfault):
list->first
应该始终存在,如果
list->numElements!=0
,那么
best
应该始终存在。但是,如果第一个元素已经是best,那么该
best
将被取消初始化,这是一个很好的观察结果。在您的示例中,尽管在一个包含单个元素的列表中它似乎是0(其中
best->next
为0表示
best==first
)。非常感谢您的评论,实际上listCount函数确保列表不为空(包含一项none NULL),当我编译时,它打印出第一块板,顶部有骑士,这意味着它确实会弹出第一个元素,但之后会出现分段错误。