2

In my code I am trying to read values from a .txt file so as to build my adjacency matrix but it keeps on returning a segmentation fault. I don't seem to be able to point out where I am going wrong. Please help.

#include <stdio.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/time.h>
#include <math.h>
#include <limits.h>
#include <iostream>


#define MAX_VERTICES 1024

int global_adj_matrix[MAX_VERTICES][MAX_VERTICES];


int **graph_tree;
int **node_data;
int global_weight;
int number_threads;
int max_nodes;
int random_node;
int max_weight;
int finish_flag;

void readAdjMatrix();


int main(int argc, char *argv[]){

    for(int i = 0 ; i < MAX_VERTICES ; i++){
        for(int j = 0 ; j < MAX_VERTICES ; j++){
            global_adj_matrix[i][j] = 0;
        }
    }

    number_threads = atoi(argv[1]);
    max_nodes = 0;

    readAdjMatrix();

}

void readAdjMatrix(){

    int source, destination, edge_weight;

    max_nodes = INT_MIN;
    max_weight = INT_MIN;

    FILE *file_pointer = fopen("graph.txt", "r");

    while(!feof(file_pointer)){
        fscanf(file_pointer, "%d", &source);
        fscanf(file_pointer, "%d", &destination);
        fscanf(file_pointer, "%d", &edge_weight);

        global_adj_matrix[source][destination] = edge_weight;
        global_adj_matrix[destination][source] = edge_weight;

        if(edge_weight > max_weight)
            max_weight = edge_weight;

        if(destination > max_nodes)
            max_nodes = destination;
    }

    printf("%d %d", max_weight, max_nodes);

    for(int i = 0 ; i <= max_nodes ; i++){
        for(int j = 0 ; j <= max_nodes ; j++){
            printf("%d\t", global_adj_matrix[i][j]);
        }
        printf("\n");
    }

    fclose(file_pointer);
}

This is my .txt file

0 1 281
0 2 242
0 3 344
0 4 340
0 5 372
0 6 161
0 7 49
0 8 278
0 10 190
0 11 213
0 12 55
0 13 239
0 14 321
0 15 162
1 0 281
1 2 249
1 3 58
1 4 331
1 5 189
1 6 84
1 7 259
1 9 256
1 11 188
1 12 149
1 13 330
1 14 17
1 15 370
2 0 242
2 1 249
2 3 125
2 4 179
2 5 355
2 6 11
2 7 232
2 8 199
2 9 67
2 10 390
2 12 312
2 13 3
2 14 237
2 15 96
3 0 344
3 1 58
3 2 125
3 4 105
3 5 192
3 6 180
3 7 335
3 8 280
3 9 185
3 10 66
3 11 65
3 13 274
3 14 72
3 15 282
4 0 340
4 1 331
4 2 179
4 3 105
4 5 149
4 6 286
4 7 265
4 8 359
4 9 341
4 10 211
4 11 367
4 12 340
4 13 14
4 14 69
4 15 128
5 0 372
5 1 189
5 2 355
5 3 192
5 4 149
5 6 167
5 7 268
5 8 20
5 9 270
5 10 210
5 11 369
5 12 131
5 13 133
5 15 167
6 0 161
6 1 84
6 2 11
6 3 180
6 4 286
6 5 167
6 7 208
6 8 335
6 9 353
6 10 12
6 11 307
6 12 199
6 13 273
6 14 118
7 0 49
7 1 259
7 2 232
7 3 335
7 4 265
7 5 268
7 6 208
7 8 182
7 9 327
7 10 272
7 11 198
7 12 103
7 13 132
7 15 161
8 0 278
8 2 199
8 3 280
8 4 359
8 5 20
8 6 335
8 7 182
8 9 108
8 10 112
8 11 344
8 12 192
8 13 264
8 14 207
8 15 231
9 1 256
9 2 67
9 3 185
9 4 341
9 5 270
9 6 353
9 7 327
9 8 108
9 10 395
9 11 205
9 12 365
9 13 8
9 14 57
9 15 132
10 0 190
10 2 390
10 3 66
10 4 211
10 5 210
10 6 12
10 7 272
10 8 112
10 9 395
10 11 11
10 12 7
10 13 288
10 14 143
10 15 226
11 0 213
11 1 188
11 3 65
11 4 367
11 5 369
11 6 307
11 7 198
11 8 344
11 9 205
11 10 11
11 12 203
11 13 136
11 14 252
11 15 168
12 0 55
12 1 149
12 2 312
12 4 340
12 5 131
12 6 199
12 7 103
12 8 192
12 9 365
12 10 7
12 11 203
12 13 90
12 14 344
12 15 11
13 0 239
13 1 330
13 2 3
13 3 274
13 4 14
13 5 133
13 6 273
13 7 132
13 8 264
13 9 8
13 10 288
13 11 136
13 12 90
13 14 39
13 15 39
14 0 321
14 1 17
14 2 237
14 3 72
14 4 69
14 6 118
14 8 207
14 9 57
14 10 143
14 11 252
14 12 344
14 13 39
14 15 154
15 0 162
15 1 370
15 2 96
15 3 282
15 4 128
15 5 167
15 7 161
15 8 231
15 9 132
15 10 226
15 11 168
15 12 11
15 13 39
15 14 154
Abhijeet Mohanty
  • 334
  • 1
  • 6
  • 21
  • 2
    This looks a lot more like C than C++ –  Apr 24 '17 at 04:23
  • Sorry about that. @InternetAussie – Abhijeet Mohanty Apr 24 '17 at 04:24
  • 2
    If it is actually C, remove the `` include, because that is C++. You are not using any element of iostream, so you do not need it. – harmic Apr 24 '17 at 04:29
  • It only segfaults for me if I do not supply an argument. How are you executing it - do you supply any arguments? – harmic Apr 24 '17 at 04:30
  • 1
    From core are you able to identify where it fails? Also you need to add check if fopen returns null – Pras Apr 24 '17 at 04:37
  • It fails when I do not enter an argument. Actually I was working on an OpenMP assignment and I am kind of a noob. Thanks a ton. – Abhijeet Mohanty Apr 24 '17 at 04:40
  • 5
    If you don't enter an arg then it should be obvious that `atoi(argv[1]);` will cause a problem because `argv[1]` will be NULL. Suggest you learn to use a debugger. – kaylum Apr 24 '17 at 04:45
  • This is not C, C doesn't have iostream`. Don't use inappropriate language tags. Select a language and write in it. – n. m. could be an AI Apr 24 '17 at 04:56
  • `` isn't used, so it can be removed –  Apr 24 '17 at 05:01
  • I am perfectly able to execute your code without getting any segmentation fault !! Why is it that you are not able to execute this ? – Coding Ninja Apr 24 '17 at 07:00
  • No doubt you gave a very good try .... but, can you please explain why you are taking an input via the command line when you are using it no where ? – Coding Ninja Apr 24 '17 at 07:04
  • @Coding Ninja It's a part of a bigger code. – Abhijeet Mohanty Apr 24 '17 at 07:28
  • @AbhijeetMohanty, your code works fine even though you have that ! I have executed it successfully on my machine without any segmentation fault. – Coding Ninja Apr 24 '17 at 07:33
  • Why have you have neglected this bigger code ? What is this bigger code doing with the smaller one ? How am I suppose to deliver the solution by keeping this neglected bigger code in mind ? Please let me know if you want me to neglect it like you have did. I post the answer as a whole for you. – Coding Ninja Apr 24 '17 at 07:40
  • I was hitting a segmentation fault in the main() itself and I want to sort things out on my own first and only then ask it as a doubt as SO responses are quick and correct, so just wanted to do it on my own. Thanks a ton. @CodingNinja – Abhijeet Mohanty Apr 24 '17 at 07:44
  • It is still not clear whether you want me to post the answer by neglecting the larger code or not. Do you want me to neglect the bigger code and post the answer ? – Coding Ninja Apr 24 '17 at 07:50
  • Yes an explanation would be nice but as far as debugging is concerned I had forgotten to mention the argument at command line. – Abhijeet Mohanty Apr 24 '17 at 07:52

2 Answers2

3

Your segmentation fault is because you're trying to read a nonexistent index in the argument vector of main. If you want to avoid that, you should rewrite it to match something like this:

int main (int argc, const char *argv[]) {

    if (argc > 1 && (number_threads = atoi(argv[1]))) {
        max_nodes = 0;
        readAdjMatrix();
    }

    return 0;
}

This ensures that you have an argument to convert to begin with, and also that it is a nonzero number. I believe atoi has undefined behavior if it isn't a valid string though, so you should harden against that. You also do some other unnecessary things. For one, this block here:

   for(int i = 0 ; i < MAX_VERTICES ; i++){
        for(int j = 0 ; j < MAX_VERTICES ; j++){
            global_adj_matrix[i][j] = 0;
        }
    }

is pointless because if you initialize a 2D array as an external/global variable then it is automatically zeroed upon initialization. Only local/automatic variables will be filled with garbage data. Therefore, you can omit it.

Finally, I would also change your while loop to look more or less like this (Credit: Chux for better loop guard).

while(fscanf(file_pointer, "%d %d %d", &source, &destination, &edge_weight) == 3) {

    global_adj_matrix[source][destination] = global_adj_matrix[destination][source] = edge_weight;

    if(edge_weight > max_weight)
        max_weight = edge_weight;

    if(destination > max_nodes)
        max_nodes = destination;
}

This ensures you correctly scanned the amount of variables necessary per line. And the extended assignment just saves a bit of room.

Hope this fixed the problem you were having.

Micrified
  • 3,338
  • 4
  • 33
  • 59
0

I am posting my answer by neglecting the bigger code which you have not mentioned in your question. I have trimmed down the unnecessary code. The code is given below.

 #include <stdio.h>
 #include <unistd.h>
 #include <ctype.h>
 #include <string.h>
 #include <stdlib.h>
 #include <math.h>
 #include <limits.h>

 #define MAX_VERTICES 1024

 int global_adj_matrix[MAX_VERTICES][MAX_VERTICES];
 int global_weight,max_nodes,random_node,max_weight;

 void readAdjMatrix();


 int main()
 {
  int i,j;

   max_nodes = 0;
   readAdjMatrix();
   return 0;
 }


 void readAdjMatrix()
 {
  int source, destination, edge_weight,i,j;
  max_nodes = INT_MIN;
  max_weight = INT_MIN;

  FILE *file_pointer = fopen("graph.txt", "r");

  while(!feof(file_pointer))
  {
    fscanf(file_pointer, "%d", &source);
    fscanf(file_pointer, "%d", &destination);
    fscanf(file_pointer, "%d", &edge_weight);

    global_adj_matrix[source][destination] = global_adj_matrix[destination][source] =edge_weight;


    if(destination > max_nodes)
        max_nodes = destination;
   }

   printf( "%d\n", max_nodes);

   for( i = 0 ; i <= max_nodes ; i++){
    for( j = 0 ; j <= max_nodes ; j++){
        printf("%d\t", global_adj_matrix[i][j]);
    }
    printf("\n");
   }

   fclose(file_pointer);
  }

PS : Simply execute this code with ./a.out with no command line argument. In case you are using the command line argument (as given in your question), please use the following syntax to execute your code :

./a.out "your desired number which works with the bigger code"

Coding Ninja
  • 114
  • 12
  • `while(!feof(file_pointer))` test is too late: code will write outside `global_adj_matrix[][]`. Better to test the result of `fscanf()`s. – chux - Reinstate Monica Apr 24 '17 at 13:40
  • How come ? The two indexes of the `global_adj_matrix[][]` array are being taken from the file (column 1 --> first index, column 2 --> second index and column 3 --> value to be stored at that location). None of the values in the file are exceeding the number `1024`. How will the data be written outside the matrix ? – Coding Ninja Apr 25 '17 at 07:49
  • After the last valid line is read with `fscanf(file_pointer, "%d", &edge_weight);`, the `while(!feof(file_pointer))` does _not_ prevent the next iteration as end-of-file has not happened yet. The 3 `fscanf()` read fail to read. In this case, likely the values of `source, destination` remain unchanged. Yet code is brittle. Should `int source, destination` get moved to inside the `while(!feof(file_pointer)) {` loop, their value would be undefined. Best to check the return of `fscanf()` & ditch `feof()`. See http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong – chux - Reinstate Monica Apr 25 '17 at 14:18
  • I really don't understand how you are telling this --> " the while(!feof(file_pointer)) does not prevent the next iteration as end-of-file has not happened yet". Of course, as stated in this link [http://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong] , it is best to use `(ch = fgetc(fp)) != EOF)` instead of `while(!feof(fp))`, but it is definitely the end of file as stated in the question. `fscanf` will scan string by string and will terminate correctly. I have executed the code perfectly (along with the text file). – Coding Ninja Apr 26 '17 at 05:41
  • After `fscanf(file_pointer, "%d", &edge_weight);` do `printf("%d\n", edge_weight);` and report if the _last_ `edge_weight` is printed once or twice. – chux - Reinstate Monica Apr 26 '17 at 12:04
  • Yes ! The last value is being printed twice ! I am not able to get you ....My question still hangs in balance ---> Why do you say that the values will be printed outside the array ? Please explain in detail. – Coding Ninja Apr 26 '17 at 13:40
  • 1
    On that last `fscanf(file_pointer, "%d", &source);`, `fscanf()` did not return 1 - the scan failed. Try `fscanf(file_pointer, "%d", &source);` --> `printf("retval:%d\n", fscanf(file_pointer, "%d", &source));`. Since it do not return 1, the value of `source` will be 1) unassigned or 2) potentially corrupted. If corrupted or never assigned, `global_adj_matrix[source][destination] = ...` is undefined behavior - access outside the array may be attempted. Robust code checks the return values of `*scanf()`. – chux - Reinstate Monica Apr 26 '17 at 13:52
  • 1
    Rather than `while(!feof(file_pointer)) { fscanf(file_pointer, "%d", &source); fscanf(file_pointer, "%d", &destination); fscanf(file_pointer, "%d", &edge_weight);` use `while(fscanf(file_pointer, "%d%d%d", &source, &destination, &edge_weight) == 3) {` – chux - Reinstate Monica Apr 26 '17 at 13:53