-1

I was implementing a graph program based on an adjacency matrix in C. But I am getting a segmentation fault while I am initializing the matrix (assigning the value of zero). I am not sure whether I am doing any mistake in accessing double pointers or not.

Can anyone please help me in resolving the issue?

Here is the code:

struct Graph {
    int V;
    int E;
    int **adj;
};


struct Graph *addelements() {
    int i,j,a,u,v;  

    struct Graph *G= (struct Graph*)malloc(sizeof(struct Graph*));
    printf("Enter the number of vertices and edges : ");
    scanf("%d %d", &G->V,&G->E);;
    printf("%d, %d\n",G->V ,G->E);
    //G->adj = (int **)malloc(sizeof(int **)*(G->V * G->E));
    G->adj = malloc(sizeof(G->V * G->E));

    //Initialization of vertices

    for(i=0;i<=G->V;i++) {
        for(j=0;i<=G->V;j++) {
            G->adj[i][j]=0;
        }
    }


    //Reading the edges;
    for(i=0;i<G->E;i++) {
        printf("Enter the source and destination : ");  
        scanf("%d %d\n", &u,&v);       
        G->adj[u][v]=1;    
        G->adj[v][u]=1;
    }

    //printing the matrix

    for(i=0;i< G->V;i++) {
        for(j=0;i< G->V;j++) {
            printf("%d", G->adj[i][j]);4
        }
    }

   return G;
}


int main() {  
    struct Graph *a= (struct Graph*)malloc(sizeof(struct Graph*)); 
    a =  addelements();  
} 

The output:

Enter the number of vertices and edges : 4 5

Segmentation fault (core dumped)

J...S
  • 5,079
  • 1
  • 20
  • 35
Ankita
  • 1
  • 3
  • Welcome to Stack Overflow! Please [edit] your question to show us what kind of debugging you've done. I expect you to have run your [mcve] within Valgrind or a similar checker, and to have investigated with a debugger such as GDB, for example. Ensure you've enabled a full set of compiler warnings, too. What did the tools tell you, and what information are they missing? And read Eric Lippert's [How to debug small programs](https://ericlippert.com/2014/03/05/how-to-debug-small-programs/). – Toby Speight Jun 01 '18 at 16:28
  • BTW, you do know that `sizeof (G->V * G->E)` is the same as `sizeof (int)`? Perhaps you wanted to `malloc(sizeof *G->adj * G->V * G->E);` instead? – Toby Speight Jun 01 '18 at 16:29

3 Answers3

2

As you mentioned your error is there

G->adj = malloc(sizeof(G->V * G->E));

//Initialization of vertices

for(i=0;i<=G->V;i++)
{
  for(j=0;j<=G->V;j++) 
  {
    G->adj[i][j]=0;
  }
}
  • You are writing at adj[V][V] where you allocated with the size of sizeof(G->V * G->E) which would be sizeof(int) ( one int ) ,even if you wanted up to adj[V][E]

  • Additionally you are allocating a 1D array and accessing a 2D array, accessing adj[0][0] would first try to read adj[0] as a pointer to an array ( an undefined value) and would try to write to undefined[0]

Allocate with malloc( G->V * G->V * sizeof(int) ) and access/write with adj[i*V+j]

There quite a few fault in your logic due to what you were expected the code to behave vs how it really understood you. It might be useful to use a debugger to understand where the fault happens and inspect the involved variable.

Edit:

Also as other answers mentionned:

you are allocating a size to small for G as malloc(sizeof(struct Graph*)) would be equivalent to malloc(sizeof(void*)) ( allocating the size of one pointer ), where you shoukd malloc(sizeof(struct Graph))

Second Edit:

Noticed a typo in your j loop for(j=0;i<=G->V;j++) should be for(j=0;j<=G->V;j++)

dvhh
  • 4,724
  • 27
  • 33
  • its still the same... getting segmentation fault. – Ankita Jun 01 '18 at 03:50
  • As noted in other comment you also have an issue with `malloc(sizeof(struct Graph*))` where you are allocating space for a pointer, use `malloc(sizeof(struct Graph))` instead. GDB would should whow where the segfault happens – dvhh Jun 01 '18 at 03:53
  • Type "apropos word" to search for commands related to "word"... Reading symbols from graph...(no debugging symbols found)...done. (gdb) r Starting program: /home/datastructures/graph Enter the number of vertices and edges : 4 5 4, 5 Program received signal SIGSEGV, Segmentation fault. 0x0000000000400702 in addelements () (gdb) (gdb) bt #0 0x0000000000400702 in addelements () #1 0x0000000000400867 in main () \(gdb) f 0 #0 0x0000000000400702 in addelements () (gdb) This is what gdb is showing – Ankita Jun 01 '18 at 03:56
  • don't forget to compile wiht the `-g` flag with would magically make debugging with gdb infinitly more useful – dvhh Jun 01 '18 at 04:07
  • oops sorry i completely forgot that... Program received signal SIGSEGV, Segmentation fault. 0x0000000000400748 in addelements () at graph.c:44 44 G->adj[i][j]=0; its showing in this line – Ankita Jun 01 '18 at 04:17
  • Is `G->adj` a valid pointer, is `G->adj[0]` an `int[]` ( spoiler: no )? Try `adj[i*V+j]`. – dvhh Jun 01 '18 at 04:20
  • still at the same location ? – dvhh Jun 01 '18 at 04:44
  • Just noticed a typo in the `j` loop, you should correct it – dvhh Jun 01 '18 at 04:56
1

I think you need to modify

struct Graph *G= (struct Graph*)malloc(sizeof(struct Graph*));

to

struct Graph *G= malloc(sizeof(struct Graph));

as you need space allocated to store a structure variable not a pointer.

And you haven't allocated space for G->adj properly.

Try

G->adj = malloc(sizeof(int **));
for(int i=0; i<G->V; ++i)
{
    G->adj[i]=malloc(sizeof(int)*G->V);
}

And modify your loop to be

for(i=0;i<G->V;i++)
{
   for(j=0;j<G->V;j++) 
   {
      G->adj[i][j]=0;
   }
}

ie, change the <= to < to prevent accessing out of bounds of the array.

And while reading the edges, don't do

scanf("%d %d\n", &u,&v);       

with the newline at the end. See this.

Also, you need to check if the entered values for u and v are within the limits as in

for(i=0;i<G->E;i++)  
{
    printf("Enter the source and destination : ");  
    scanf("%d %d", &u,&v);       
    if(u<G->V && v<G->V)
    {
        G->adj[u][v]=1;    
        G->adj[v][u]=1;
    }
    else
    {
        printf("\ninvalid value. Try again.");
        i--;
    }
}

And you needn't allocate space for that struct pointer in main() as you already allocate memory for the value that you will store in that pointer at the addelements() function. Otherwise it will lead to memory leak.

So, in main(), do

struct Graph *a= addelements();

Note that malloc() returns NULL if it failed to allocate memory. You need to check if the malloc() calls fail as well.

And you needn't cast the return value of malloc() in C. Read this.

J...S
  • 5,079
  • 1
  • 20
  • 35
  • i did it... but still it is showing segmentation fault.... its problem with the //Initialization of vertices part... – Ankita Jun 01 '18 at 03:42
  • @Ankita I've edited my post. See if it works for you. – J...S Jun 01 '18 at 04:02
  • @Ankita Still segmentation fault? – J...S Jun 01 '18 at 04:12
  • i have used gdb ... it is showing in this particular line... Program received signal SIGSEGV, Segmentation fault. 0x0000000000400748 in addelements () at graph.c:44 44 G->adj[i][j]=0; – Ankita Jun 01 '18 at 04:18
  • i am not sure what is the correct way of accessing it – Ankita Jun 01 '18 at 04:19
  • @Ankita Did you `malloc()` for `G->adj` as in my answer? If that's the way you allocated for `adj`, you can access it like `G->adj[i][j]` itself. – J...S Jun 01 '18 at 04:19
  • Yup i malloc() for G->adj as you said... i did that changes too... but its stiill the same – Ankita Jun 01 '18 at 04:26
  • @Ankita Can you post the modified code somewhere and share the link? [ideone](https://ideone.com) maybe? – J...S Jun 01 '18 at 04:31
  • @Ankita I can't find the problem. I could find no difference between your code and mine. – J...S Jun 01 '18 at 04:56
  • @Ankita Finally got something. You haven't modified the loops. The inner loop for initialising the `adj` array has condition `iV` instead of `jV`. Same in the case of printing the matrix. – J...S Jun 01 '18 at 05:33
  • @Ankita Also, remove the `\n` at the end of the `scanf()`. – J...S Jun 01 '18 at 05:39
  • thank you so much for the help... it worked completelyyyy – Ankita Jun 02 '18 at 04:07
0

You are mallocing space for just a pointer. Use instead:

malloc(sizeof(struct Graph));
J...S
  • 5,079
  • 1
  • 20
  • 35
rslemos
  • 2,454
  • 22
  • 32