释放导致崩溃

时间:2018-05-02 15:22:30

标签: c malloc

我目前正在实现Dijkstra算法的伪代码,我在释放节点方面遇到了麻烦。我的代码似乎工作正常,除了释放部分。我已经释放了代码中的所有malloc,但它仍然在崩溃。

我已经检查了可能发生的所有可能的“错误”,我现在仍然坚持这个。

这是我的代码。

#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <string.h>
#include <math.h>

//#####################################################################
//#####################################################################
//#####################################################################

//#####################################################################
//######################### Structures ################################
//#####################################################################

struct node
{
    int vertex;
    int cost;
    struct node* next;
};

struct PQ
{
    int* heap;
    int* index;
    double* key;
    int sizePQ;
};

//#####################################################################
//######################### Graph Things ##############################
//#####################################################################

struct node* createNode(int v,int cost)
{
    struct node* newNode = malloc(sizeof(struct node));
    newNode->vertex = v;
    newNode->cost = cost;
    newNode->next = NULL;
    return newNode;
}

struct G{
    int n;
    int* pred;
    double* dist;
    struct node** LIST;
};

struct G* initGraph(int vertices)
{
    struct G* graph = malloc(sizeof(struct G));
    graph->n = vertices-1;

    graph->LIST = malloc(vertices * sizeof(struct node*));
    graph->pred = malloc(vertices * sizeof(int));
    graph->dist = malloc(vertices * sizeof(double));

    int i;
    for (i = 0; i <= vertices; i++)
        graph->LIST[i] = NULL;

    return graph;
}

void addEdge(struct G* graph, int src, int dest, int cost)
{
    struct node* newNode = createNode(dest, cost);
    newNode->next = graph->LIST[src];
    graph->LIST[src] = newNode;
}

void freeG(struct G* graph){
    int v;
    for (v = 0; v <= graph->n+1; v++)
    {
        struct node* temp = graph->LIST[v];
        struct node* temp2 = temp->next;
        while (temp!=NULL)
        {
            free(temp);
            temp = temp2;
            temp2 = temp->next;
        }
    }
    free(graph->pred);
    free(graph->dist);
    free(graph->LIST);
    free(graph);
}

void freePQ(struct PQ* PQ){
    free(PQ->heap);
    free(PQ->key);
    free(PQ->index);
    free(PQ);
}
//#####################################################################
//############################ Procedures #############################
//#####################################################################

void PQ_UNDERFLOW(){
    printf("Underflow Detected");
}

void InitPQ(struct G* G,struct PQ* PQ, int s){
    PQ->heap = malloc(G->n * sizeof(int));
    PQ->index = malloc(G->n * sizeof(int));
    PQ->key = malloc(G->n * sizeof(double));
    PQ->sizePQ = G->n;
   // printf("%i",G->n);

    int i = 1;
    int v;
    for(v=1;v<=G->n;v++){
        if(v==s){
            PQ->heap[1]=s;
            PQ->index[s]=1;
            PQ->key[s]=0;
        }
        else{
            ++i;
            PQ->heap[i]=v;
            PQ->index[v]=i;
            PQ->key[v]=INFINITY;
           // printf("%i//",PQ->heap[i]);
            //printf("%lf ",PQ->key[v]);
        }
    }
}

void HEAPIFY(struct PQ* PQ,int r){
    //printf("%i",PQ->heap[r]-1);
    double k = PQ->key[PQ->heap[r]];
    int l = PQ->heap[r];
    int i = r, j = 2*i;
    while(j<=PQ->sizePQ){
        if (j<PQ->sizePQ && PQ->key[PQ->heap[j+1]]< PQ->key[PQ->heap[j]]){
            ++j;
        }
        if(PQ->key[PQ->heap[j]]<k){
            PQ->heap[i]=PQ->heap[j];
            PQ->index[PQ->heap[j]]=i;
            i=j;
            j=2*i;
        }else break;
    }
    PQ->heap[i]=l;
    PQ->index[l]=i;
}

int IsEmptyPQ(struct PQ* PQ){
    return(PQ->sizePQ==0);
}

void EXTRACT_MIN(struct PQ* PQ, int *j){

    if (PQ->sizePQ == 0) PQ_UNDERFLOW();
    else{
        *j=PQ->heap[1];
        PQ->heap[1] = PQ->heap[PQ->sizePQ];
        PQ->index[PQ->heap[1]]=1;
        PQ->sizePQ=PQ->sizePQ-1;
        HEAPIFY(PQ,1);
    }
}

void DECREASE_KEY(struct PQ* PQ, int l, double newkey){
    PQ->key[l] = newkey;
    int i = PQ->index[l];//printf("pqindexl->%i\n",PQ->index[l]);
    int j =floor(i/2);
    while (i > 1 && PQ->key[PQ->heap[j]]>newkey){
        PQ->heap[i]= PQ->heap[j];
        PQ->index[PQ->heap[j]]=i;
        i=j; j =floor(i/2);
    }
    PQ->heap[i]=l;
    PQ->index[l]=i;
}
//#####################################################################
//############################ DIJKSTRA   #############################
//#####################################################################

void DIJKSTRA(struct G* G, struct PQ* PQ, int s){
    InitPQ(G,PQ,s);
    int u = 0,v;
    double newval;
    G->pred[s]=0;
    while(!IsEmptyPQ(PQ)){
        EXTRACT_MIN(PQ,&u);
        if (PQ->key[u]== INFINITY){break;}
        struct node* a = G->LIST[u];
        while (a!=NULL)
        {
            v = a->vertex;//printf("vertex = %i\n",a->vertex);
            newval = PQ->key[u]+a->cost;
            if (PQ->key[v]>newval){
                G->pred[v]=u;
                DECREASE_KEY(PQ,v,newval);
            }
            a = a->next;
        }
    }
    G->dist=PQ->key;
}


//#####################################################################
//############################  print g   #############################
//#####################################################################

void DISPLAY_PATH(struct G* G, int s,int v){
    int path[G->n];
    int len = 1;
    path[len]=v;
    int i=v;
    while(i!=s){
        if(G->pred[i]==0){printf("No path found");return;}
        else{
            i = G->pred[i];
            ++len;
            path[len]=i;
        }
    }
    printf("Shortest path found: ");
    while(len>=1){
        printf("%i",path[len]);
        if(len!=1)printf(" -> ");
        len--;
    }
}

void printGraph(struct G* graph)
{
    int v;
    for (v = 1; v <= graph->n; v++)
    {
        struct node* temp = graph->LIST[v];
        printf("\n Adjacency list of vertex %d\n ", v);
        while (temp)
        {
            printf("%d -> ", temp->vertex);
            temp = temp->next;
        }
        printf("\n");
    }
}
//#####################################################################
//#####################################################################
//#####################################################################
int main()
{
    struct G* graph = initGraph(10);
    addEdge(graph, 1, 2, 4);
    addEdge(graph, 1, 8, 8);
    addEdge(graph, 2, 3, 8);
    addEdge(graph, 2, 8, 11);
    addEdge(graph, 3, 4, 7);
    addEdge(graph, 3, 9, 2);
    addEdge(graph, 3, 6, 4);
    addEdge(graph, 4, 5, 9);
    addEdge(graph, 4, 6, 14);
    addEdge(graph, 5, 6, 10);
    addEdge(graph, 6, 7, 2);
    addEdge(graph, 7, 8, 1);
    addEdge(graph, 7, 9, 6);
    addEdge(graph, 8, 9, 7);
    printGraph(graph);
    printf("\n");

    struct PQ* PQ=malloc(sizeof(struct PQ));
    DIJKSTRA(graph, PQ, 1);
    DISPLAY_PATH(graph,1,8);

    freePQ(PQ);
    freeG(graph);
}

除了释放部分外,一切正常。它打印算法的所需输出,但在程序结束时崩溃。

我也非常想了解malloc和freeing是如何工作的,这可能会给我更多关于它的信息。

Here's what happens everytime I run it

编辑:我在我的代码上运行了valgrind,它似乎得到一个名为“core dumped”的错误。据我所知,当我释放一个节点两次或更多时,会发生核心转储错误。我的免费代码中没有看到任何错误。

Here is what valgrind outputs

2 个答案:

答案 0 :(得分:1)

你尝试过使用Valgrind吗?如果是的话,有任何错误吗?

Valgrind是一个检查内存泄漏和内存违规的工具。它会自行替换您的系统malloc来观察您的行为。

另外请避免使用UPPERCASE函数,这些函数应保留用于宏函数和宏函数(#define)。 您还应该使用typedef重命名结构。 例如,

typedef struct s_myStruct
{
  ...
} t_myStruct;

t_mystruct *st = malloc(sizeof(t_mystruct));

答案 1 :(得分:0)

这段代码似乎错了:

for (v = 0; v <= graph->n+1; v++)
{
    struct node* temp = graph->LIST[v];

n初始化为9 initGraph时,此代码将循环播放v = 0,1,...,10

但是,在initGraph中,您可以使用10个元素,因此现在可以访问LIST超出界限。

尝试

for (v = 0; v < graph->n+1; v++)
{
    struct node* temp = graph->LIST[v];

代替。

然后看看:

    struct node* temp = graph->LIST[v];
    struct node* temp2 = temp->next;

如果graph->LIST[v]为NULL,会发生什么?

执行此操作时程序将崩溃:

temp2 = temp->next

因此,您需要将代码转换为:

    struct node* temp = graph->LIST[v];
    while (temp!=NULL)
    {
        struct node* temp2 = temp->next;
        free(temp);
        temp = temp2;
    }