2

I realize it gets kind of long with all the printf, but I didn't really know how to present my issue better.

I am having problems initializing a struct in c properly. I have tried debugging with printf to show my issue. Essentially I'm creating a list of structs, using the following function:

Vertex *Vertex_new(int n){
    Vertex *vert = malloc(sizeof(Vertex));
    if(!vert){return NULL;}

    vert->id = n;
    vert->outNeighbours = malloc(sizeof(LinkedList));
    vert->outNeighbours = LinkedList_new();
    vert->inNeighbours = malloc(sizeof(LinkedList));
    vert->inNeighbours = LinkedList_new();

    return vert;
}

struct Vertex {
    int id; // a number in [0; numVertices[
    LinkedList *outNeighbours; // A linked list of vertices.
    LinkedList *inNeighbours; // A linked list of vertices
};

And that is used for the creation of the following struct, with function right after. The function after, called Graph_new(), I have an issue with saving the Vertex, properly inside the list. I don't know which part I'm doing wrong, but I'm assuming it's something to do with how I'm initializing the list, and as such made a bunch of print statements to try and understand the problem:

struct Graph {
    int numVertices;
    int numEdges;
    Vertex *vertices; // An array of numVertices vertices
};



Graph *Graph_new(int n){
    Graph *grf = malloc(sizeof(Graph));
    if(!grf){return NULL;}

    grf->numEdges = 0;
    grf->numVertices = n;

    Vertex list[n];
    grf->vertices = malloc(sizeof(Vertex*)*n);

    for(int i = 0; i < n;i++){
        list[i] = *Vertex_new(i);
    }
    grf->vertices = list;

    // My attempt at debugging, `grf` is simply returned after these print statements:
    printf("Inside graph_new for list:\n");
    printf("%d ",list[0].id);
    printf("%d ",list[1].id);
    printf("%d ",list[2].id);
    printf("%d ",list[3].id);
    printf("%d \n",list[4].id);
    // Det her virker herinde, men ikke uden for
    // er der et problem i hvordan jeg gemmer listen?
    printf("Inside graph_new for grf->vertices:\n");
    printf("%d ",grf->vertices[0].id);
    printf("%d ",grf->vertices[1].id);
    printf("%d ",grf->vertices[2].id);
    printf("%d ",grf->vertices[3].id);
    printf("%d \n",grf->vertices[4].id);

    printf("%d ",grf->vertices[0].id);
    printf("%d ",grf->vertices[1].id);
    printf("%d ",grf->vertices[2].id);
    printf("%d ",grf->vertices[3].id);
    printf("%d \n",grf->vertices[4].id);



    return grf;
}

In another function, I call graph_new(n). n is here read from a file, n in this case is 5, which I have tested, to make sure it reads it correctly, so it's a guaranteed 5. I tested two way of printing, in order to understand what is happening. The first:

Graph *newG = Graph_new(n);


// outside of graph_new:
printf("outside of graph_new, newG->vertices:\n");
printf("%d ",newG->vertices[0].id);
printf("%d ",newG->vertices[1].id);
printf("%d ",newG->vertices[2].id);
printf("%d ",newG->vertices[3].id);
printf("%d \n",newG->vertices[4].id);
printf("%d ",newG->vertices[0].id);
printf("%d ",newG->vertices[1].id);
printf("%d ",newG->vertices[2].id);
printf("%d ",newG->vertices[3].id);
printf("%d \n",newG->vertices[4].id);

Gives the output:

Inside graph_new for list:
0 1 2 3 4 
Inside graph_new for grf->vertices:
0 1 2 3 4 
0 1 2 3 4 
outside of graph_new, newG->vertices:
0 -285208794 -603392624 -603392624 0 
0 -285208794 -603392624 -603392624 0

So at first I assumed it was because the list was not saved properly, or the vertices was not saved properly inside the list.

But if I then print this outside of Graph_new:

Vertex vert1 = newG->vertices[0];
Vertex vert2 = newG->vertices[1];
Vertex vert3 = newG->vertices[2];
Vertex vert4 = newG->vertices[3];
Vertex vert5 = newG->vertices[4];
printf("works outside:\n");
printf("%d ", vert1.id);
printf("%d ", vert2.id);
printf("%d ", vert3.id);
printf("%d ", vert4.id);
printf("%d \n", vert5.id);  

// Saving the vertices back in the array works
newG->vertices[0] = vert1;
newG->vertices[1] = vert2;
newG->vertices[2] = vert3;
newG->vertices[3] = vert4;
newG->vertices[4] = vert5;

Vertex vert11 = newG->vertices[0];
Vertex vert22 = newG->vertices[1];
Vertex vert33 = newG->vertices[2];
Vertex vert44 = newG->vertices[3];
Vertex vert55 = newG->vertices[4];  
printf("Works again\n");
printf("%d ", vert11.id);
printf("%d ", vert22.id);
printf("%d ", vert33.id);
printf("%d ", vert44.id);
printf("%d \n", vert55.id);
// ------------------------------

printf("Doesn't work: \n");
Vertex vvert1 = newG->vertices[0];
Vertex vvert2 = newG->vertices[1];
Vertex vvert3 = newG->vertices[2];
Vertex vvert4 = newG->vertices[3];
Vertex vvert5 = newG->vertices[4];
printf("%d ", vvert1.id);
printf("%d ", vvert2.id);
printf("%d ", vvert3.id);
printf("%d ", vvert4.id);
printf("%d \n", vvert5.id);

I get the following output:

Inside graph_new for list:
0 1 2 3 4 
Inside graph_new for grf->vertices:
0 1 2 3 4 
0 1 2 3 4 
works outside:
0 1 2 3 4 
Works again
0 1 2 3 4 
Doesn't work: 
0 -2035597530 519880720 -2031896736 -1398417392

If anyone is has the time to understand it and give a helping hand, I'd REALLY appreciate it. I might not make it in time for the exam, but at least I'd know what I did wrong.

5
  • 2
    Why are you overwriting outNeighbour and inNeighbour immediately after mallocing? Commented Dec 11, 2019 at 10:56
  • I would recommend separating your allocation and your initialisation. Commented Dec 11, 2019 at 10:58
  • @kiranbiradar from an earliyer part that bugged me, thanks for pointing it out. Commented Dec 11, 2019 at 11:06
  • @jjh Are you referring to the Linkedlist allocation? Commented Dec 11, 2019 at 11:06
  • Instead of doing this, Vertex list[n]; , do Vertex* list; and allocate memory to list by doing, list = (Vertex*) malloc(n*sizeof(Vertex)); and then add each vertex to list as you did. then assign list pointer to vertices pointer. When you declare list as an array, it will be created in stack, which can not be accessed outside Graph_new. Commented Dec 11, 2019 at 11:13

1 Answer 1

3
Graph *Graph_new(int n){
    …

    Vertex list[n];
    grf->vertices = malloc(sizeof(Vertex*)*n);

    for(int i = 0; i < n;i++){
        list[i] = *Vertex_new(i);
    }
    grf->vertices = list;

    …

    return grf;
}

list array is local to Graph_new function and will be destroyed once control exits the function, thus you cannot take reference of list out of Graph_new it is undefined behavior.

Also *Vertex_new(i); has memory leaks, as you are loosing reference to the allocation.

Sign up to request clarification or add additional context in comments.

5 Comments

So how would i then save the list of vertex? I'm assuming you mean i would save it directly to grf->vertices, but i'm not sure how to iterate through it
As a pointer, i just exchanged list with grf-vertices, and somehow it gave me the correct output for all my prints statements so far. If that was it, you are a god
@Stoxhorn You need to allocate memory to verices --> grf->vertices = malloc(sizeof(Vertex ) *n) ; before accessing it.
Already did that, but it was really just the whole assigning to list instead of grf->vertices.
@Stoxhorn You are allocating wrongly, grf->vertices = malloc(sizeof(Vertex*)*n); --> grf->vertices = malloc(sizeof(Vertex)*n);. Also consider my point about memory leak.

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.