我有以下代码从列表中删除元素。当结构的一个元素低于我使用它的值时,我必须删除该节点。
代码如下:
void DeleteNode(frota** head, int MAX, int nSquareW){
int i, eliminate = 0;
frota* curr = *head;
frota* curr1 = curr;
if(*head != NULL)
{
while(curr1 != NULL)
{
if(curr1->bateria < MAX)
{
if( *head == curr1){
if(curr1->next != NULL){
(curr1->next)->prev = NULL;
}
*head = curr1->next;
}else if(curr1 -> next == NULL){
(curr1->prev)->next = NULL;
}else{
(curr1->next)->prev = curr1->prev;
(curr1->prev)->next = curr1->next;
}
eliminate = 1;
}
curr1 = curr1->next;
if(eliminate == 1){
eliminate = 0;
printf("entrei1");
for(i=0;i<nSquareW;i++){
free(curr->percorridos[i]);
}
free(curr->percorridos);
free(curr);
}
curr = curr1;
}
}
}
当我尝试删除最后和中间节点时代码运行良好(值头等于第一个节点,除非没有,然后值为NULL),但是当我尝试删除第一个节点时,我得到以下错误:
*** Error in './iClean': double free or corruption (!prev): 0x09bd4a20 ***
有人已经告诉我问题在于删除节点(free())并且我无法做任何事情。
任何帮助都会受到赞赏。
修改
nSquareWidth是地图的宽度。
这是生成percorridos的代码:
void faz_mapa(matriz *** mapa, int nSquareW, int nSquareH){
*mapa = malloc(nSquareW * sizeof(matriz*));
for (int i = 0; i < nSquareW; i++)
{
(*mapa)[i]= malloc( nSquareH * sizeof(matriz));
}
for (int i = 0; i < nSquareW; i++)
{
for (int j = 0; j < nSquareH; j++)
{
//inicializa divisao suja
(*mapa)[i][j].limpo = 0;
(*mapa)[i][j].ocupado = NULL;
}
}
}
结构:
typedef struct robot {
int bateria;
char nome[STRING_SIZE];
int pos_x;
int pos_y;
int target_x;
int target_y;
int limpos;
matriz ** percorridos;
struct robot * next;
struct robot * prev;
}frota;
答案 0 :(得分:0)
我没有运行你的代码,但显然只有一个地方我们可以遇到双重免费。
for(i=0;i<nSquareW;i++){
free(curr->percorridos[i]);
}
free(curr->percorridos);
free(curr);
您是否有curr->percorridos
与curr
相同的情况,或者curr->percorridos[i]
与curr->percorridos
相同?
你可以通过在每次免费电话会议之前添加一个print语句来找到它。然后找出哪两个被调用。
for(i=0;i<nSquareW;i++){
printf("Freeing curr->perrcorridos[i] at %p\n", curr->percorridos[i]);
free(curr->percorridos[i]);
}
printf("Freeing curr->perrcorridos at %p\n", curr->percorridos);
free(curr->percorridos);
printf("Freeing curr at %p\n", curr);
free(curr);
答案 1 :(得分:0)
由于双链表编程问题经常出现在Stack Overflow上,我的答案将展示如何以一种非常安全的方式进行双链表。它使用顶级列表类型定义和标记条目。仍然有一些空间,但代码很容易测试和调试,因为不同的方面由各个函数在本地处理。
原始问题中的delete()函数存在以下问题:它负责两个不同的事情:1。处理双链表删除内容2.做一些特定于应用程序的过滤。
我的代码还显示,在这样的列表上运行的应用程序代码可以与列表管理代码分开。
#include <stdint.h>
#include <stdlib.h>
typedef struct NodeType_tag { int32_t value; NodeType_tag *Next; NodeType_tag *Prev; } NodeType;
typedef struct { NodeType sentinel; NodeType *head; NodeType *tail; } NodeList;
void NodeListInit(NodeList * nodeList)
{
nodeList->sentinel.Next = &nodeList->sentinel;
nodeList->sentinel.Prev = &nodeList->sentinel;
nodeList->head = &nodeList->sentinel;
nodeList->tail = &nodeList->sentinel;
}
int NodeListIsEmpty(NodeList * nodeList)
{
return nodeList->head == &nodeList->sentinel;
}
void NodeListAddFront(NodeList* nodeList, uintptr_t value)
{
NodeType *newNode = (NodeType*)malloc(sizeof(NodeType));
if (NULL != newNode)
{
newNode->value = value;
newNode->Prev = nodeList->head->Prev;
newNode->Next = nodeList->head;
nodeList->head->Prev = newNode;
nodeList->head = newNode;
if (nodeList->tail == &nodeList->sentinel)
nodeList->tail = newNode;
}
}
void NodeListAddBack(NodeList* nodeList, int32_t value)
{
NodeType *newNode = (NodeType*)malloc(sizeof(NodeType));
if (newNode != NULL)
{
newNode->value = value;
newNode->Prev = nodeList->tail;
newNode->Next = nodeList->tail->Next;
nodeList->tail->Next = newNode;
nodeList->tail = newNode;
if (nodeList->head == &nodeList->sentinel)
nodeList->head = newNode;
}
}
NodeType *NodeListHead(NodeList*nodeList)
{
if (&nodeList->sentinel != nodeList->head)
return nodeList->head;
return NULL;
}
NodeType *NodeListTail(NodeList* nodeList)
{
if (&nodeList->sentinel != nodeList->tail)
return nodeList->tail;
return NULL;
}
NodeType *NodeListNext(NodeList * nodeList, NodeType * current)
{
if (NULL != current)
{
if (current->Next != &nodeList->sentinel)
return current->Next;
}
return NULL;
}
NodeType *NodeListPrev(NodeList *nodeList, NodeType *current)
{
if (NULL != current)
{
if (current->Prev != &nodeList->sentinel)
return current->Prev;
}
return NULL;
}
NodeType* NodeListRemoveForward(NodeList* nodeList, NodeType *target)
{
NodeType* next = NULL;
if (target != NULL)
{
target->Prev->Next = target->Next;
target->Next->Prev = target->Prev;
if (target == nodeList->head)
nodeList->head = target->Next;
if (target == nodeList->tail)
nodeList->tail = target->Prev;
if (&nodeList->sentinel != target->Next)
next = target->Next;
free(target);
}
return next;
}
// return 1 if value passes filter.
// return 0 if value is not passing filter.
typedef int(*FilterFunction_t)(int32_t value);
size_t NodeListFilter(NodeList *nodeList, FilterFunction_t filter)
{
NodeType * current = NodeListHead(nodeList);
size_t removeCount = 0;
while (current != NULL)
{
if (filter(current->value))
{
// passed filter -> keep it.
current = NodeListNext(nodeList, current);
}
else
{
// did not pass filter - kill it!
current = NodeListRemoveForward(nodeList, current);
removeCount++;
}
}
return removeCount;
}
void NodeListClear(NodeList *nodeList)
{
NodeType *current = NodeListHead(nodeList);
while (current != NULL)
{
current = NodeListRemoveForward(nodeList, current);
}
}
void DumpNodeList(NodeList* nodeList)
{
NodeType * current = NodeListHead(nodeList);
size_t i;
for (i = 0; current != NULL; i++, current = NodeListNext(nodeList,current))
{
printf("%d: %d\n", i, current->value);
}
}
int FilterAllOddValues(int32_t value)
{
if (0 == value % 2)
return 1;
return 0;
}
void TestNodeList()
{
NodeList myNodeList;
NodeListInit(&myNodeList);
for (int32_t value = 0; value < 10; value++)
{
NodeListAddBack(&myNodeList, value);
}
DumpNodeList(&myNodeList);
size_t removeCount = NodeListFilter(&myNodeList, FilterAllOddValues);
printf("%d nodes removed by filter.\n", removeCount);
DumpNodeList(&myNodeList);
NodeListClear(&myNodeList);
}
一个显而易见的方面是,与非哨兵实施相比,头/尾特殊处理if-branches的数量大大减少。
另一个显而易见的方面是我使用c ++编译器运行它,因此在malloc()语句中添加了一个强制转换。请拒绝写出评论的冲动,例如“Do not cast malloc()”,所有你的核心c程序员;)
我使用下面给出的测试代码进行了简短的冒烟测试。测试代码未涵盖的功能可能仍有错误。