-4

While implementing a Dijkstra-Search on a Graph, I call a seperate method to perform the search, handing it a pointer to my nodes and direct values for start/endpoint and array size. Notably,t he method doesn't change anything about the node array, it only reads values.

When I try to free the node array after, it causes a SIGSEGV

int djkstra(int start, int goal, node* v, int n){
   //Algorithm logic
   return result;
}
int main(){ [...]
   node* v = (node*)malloc(sizeof(node)*(n+1));
   djkstra(start, goal, v, n);
   free(v); //This throws a SIGSEGV
   return 0;}

I can't find anything online about why this might cause things to break. I tried adding a seperate array declared in main as well (which gets changed in the method), which I also couldn't free after.

Is this some kind of obscure C++ rule? I couldn't find anything online about this, and the method should be long resolved when I call free(v).

I'll put a working example here for clarification, though note there is another strange free() segfault in djkstra which I'll probably need to make another question for later.

#include <iostream>
#include <stdio.h>

class node{
    public: int edges;
    public: int* pre;
    public: int* cost;

    public: void addpre(int i, int c){/*Insertion logic*/}
    public: void destroy(){/*Frees the arrays*/}
};
int djkstra(int start, int goal, node* v, int n){

    bool* visited =(bool*)malloc(sizeof(bool)*n+1);
    int* costss = (int*)malloc(sizeof(int)*n+1);
    for(int i=0; i<=n; i++){
         costss[i]=5000001;
         visited[i]=false;
    }


    bool allvisit=false;
    costss[start]=0;
    while(true){
        int smallest=5000000;
        int cur=0;
        for(int i=1; i<=n; i++){
            if(!visited[i] && costss[i]<smallest){
                smallest=costss[i];
                cur=i;
            }
        }
        if(cur==0){allvisit=true; break;}
        if(cur==goal){break;}
        visited[cur]=true;
        for(int j=0; j<v[cur].edges; j++){
            int jcost=v[cur].cost[j]+smallest;
            if(jcost<costss[v[cur].pre[j]]){
                costss[v[cur].pre[j]]=jcost;
            }
        }

    }
    int res;
    if(allvisit){res=5000000;}
    else{res=costss[goal];}

    free(visited);
    free(costss); //Freeing this causes SIGSEGV
    return res;
};
int main() {
    int n=2; //number of nodes
    int s=2; //number of waypoints
    node* v = (node*)malloc(sizeof(node)*(n+1));
    int* costs = (int*)malloc(sizeof(int)*s); //Saving cost of waypoints
    int* market = (int*)malloc(sizeof(int)*s); //Saving location of waypoints
    //Example case
    int start=1;
    int goal=2;
    v[1].edges=1;
    v[2].edges=1;
    v[1].pre=(int*)malloc(sizeof(int));
    v[1].pre[0]=2;
    v[2].pre=(int*)malloc(sizeof(int));
    v[2].pre[0]=1;
    v[1].cost=(int*)malloc(sizeof(int));
    v[2].cost=(int*)malloc(sizeof(int));
    v[2].cost[0]=30;
    v[1].cost[0]=30;
    costs[0]=15;
    costs[1]=20;
    market[0]=1;
    market[1]=2;

    int mincost=5000000;
    for(int i=0; i<s; i++){
        int j=djkstra(start, market[i], v, n);
        costs[i]=costs[i]+j;
    }
    for(int i=0; i<s; i++){

        costs[i]=costs[i]+djkstra(market[i], goal, v, n);
        if(costs[i]<mincost){mincost=costs[i];}

    }

    if(mincost==5000000){printf("impossible\n");}
    else{
        int hours=mincost/60;
        int minutes=mincost-(hours*60);
        if(minutes<10){printf("%d:0%d\n", hours, minutes);}
        else{printf("%d:%d\n", hours, minutes);}
    }

    for(int i=1; i<=n; i++){
       v[i].destroy();
    }
    free(market); //Freeing this works fine
    free(costs); //Freeing this works fine
    free(v); //Freeing this causes SIGSEGV
    return 0;
 }
8
  • 5
    bool* visited =(bool*)malloc(sizeof(bool)*n+1); is not the same as bool* visited =(bool*)malloc(sizeof(bool)*(n+1)); I haven't looked further, but the program likely exhibits undefined behavior by way of a buffer overrun, and corrupts the heap. Commented Nov 7 at 2:02
  • 5
    This is not C++, this is C with classes, even class node is used as a C struct. Commented Nov 7 at 2:05
  • 3
    First thing is to replace all those malloc/free stuff with new/delete or standard library constructs like std::vector. Even if you can find out what goes wrong here this time, such memory-related error will show up again and again due to the bad coding habits. Commented Nov 7 at 4:24
  • 1
    Generally, when you need to use an explicit C-style conversion (like the cast of the result from malloc) you should take that as a sign that you're likely are doing something wrong. Commented Nov 7 at 4:49
  • 3
    "How do pointers work after pass-by-reference?" -- How does this relate to the body of your question? None of your functions take their parameters by reference. Commented Nov 7 at 6:13

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.