Reason for segfault in C program?

Apr 23, 2012 at 3:50am
hi everyone im working on a program so far and I've gotten the dreaded segmentation fault which I always seem to get. I've run gdb and backtraced it to fgets in main. What am i doing wrong? Any help is greatly appreciated!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include "intList.h"
#include "intList.c"

typedef struct Edge {
   int from, to;
   double weight;
}Edge;

IntList* initedges(int n){
   IntList* adjvertices = calloc(n+1,sizeof(IntList));
   int itora;
   for( itora = 0; itora <= n; itora++){
      adjvertices[itora] = NULL;
   }
   return (adjvertices);
}

Edge parseedge(char* line){
   Edge newedge;
   int nwords = sscanf(line, " %d %d %f",&newedge.from, &newedge.to, &newedge.weight);
   if(nwords < 2 || nwords > 3){
      char tempo[1024];
      perror(strcat(strcpy(tempo,"Bad edge: "), line));
      exit(1);
   }
   if (nwords == 2) newedge.weight = 0.0;
   return newedge;
}

int parsen(char* line){
   int n;
   if(sscanf(line, "%i", &n) != 1){
      char temp[1024];
      perror(strcat(strcpy(temp, "Bad line 1: "), line));
      exit(1);
   }
   return n;
}

int loadedges(FILE* inbuf, IntList* adjvertices){
   Edge newele;
   int m = 0;
   char *line;
   fgets(line, sizeof(line), inbuf);
   while(line!=NULL){
      newele = parseedge(line);
      adjvertices[newele.from] = cons(newele.to, adjvertices[newele.from]);
      ++m;
      fgets(line, sizeof(line), inbuf);
   }
   return m;
}


int main(int argc, char* argv[]){
   int a, b;
   IntList* adjvert;
  
   if(argc == 0){
      printf("Usage: graph < input.data");
      exit(0);
   }

   char *infile= argv[2];
   FILE *inbuf = fopen(infile, "r");
   printf("Opened %s for input.", infile);
   char line[1024];
   fgets(line, 1024, inbuf);
   b = parsen(line);
   printf("n = %d", b);

   adjvert = initedges(b);
   a = loadedges(inbuf, adjvert);
   fclose(inbuf);
   printf("m = %d", a);
   
   int itor;
   for(itor = 0; itor<=b; itor++){ 
     printf("%d\t%s", itor, tostring(",",adjvert[itor])); 
   }
}
Apr 23, 2012 at 5:58am
I didn't look that close, but I did notice some weirdness:

line 62, 67: argc is never zero. It always has to at least be 1. Remember:

argv[0] = program name (usually)
argv[1] = first parameter
argv[2] = second parameter
... etc

So if you need the program to be called with at least 1 parameter, then argc must be >= 2, and you want to use argv[1], not argv[2].


I find it unlikely that that would cause a segfault though.

Apr 23, 2012 at 6:27am
Hi Disch,

Thanks for taking the time to reply. I did change argv[2] to argv[1] as the input file directly following the program name is what i wanted but that didnt fix the problem. After digging deeper I found that it is a problem with inbuf on line 68. I suspect that fopen is not giving me what I want and causes fgets to be called with a random pointer causing a segfault.
Apr 23, 2012 at 8:12am
fopen returns a null pointer when it fails. You're not checking that anywhere.
And how did you expect the following to work?
1
2
char *line;
fgets(line, sizeof(line), inbuf);
Apr 23, 2012 at 9:32am
Athar,

Just noticed that issue and tried putting

if (inbuf != NULL)

before line 68 which fixes the problem. However, now I am getting a seg fault
at the fgets in function loadedges although i do not know which one. I have added a check for inbuf in loadedges as well but the result is the same.

i hate seg faults.
Apr 23, 2012 at 10:21am
However, now I am getting a seg fault
at the fgets in function loadedges although i do not know which one.

See the second part of my previous post.
Apr 23, 2012 at 10:47am
Ah sorry, i mustve forgotten to respond to your second part in my frustration. On the reference page for fgets on this site, it says that fgets is to be used
in this manner

char * fgets ( char * str, int num, FILE * stream );

with "...in the string copied to str." in this description. I took this to mean that whatever fgets returns, it returns to the first parameter. In essence, I expect line to contain the contents of the user specified file (should be a .txt file with numbers as well as whitespace,newline).

I tried char *line2 = fgets
Last edited on Apr 23, 2012 at 11:30am
Apr 23, 2012 at 10:49am
line is an uninitialized pointer which is pointing to some random location in memory.
It is supposed to point to a buffer where fgets can store the data.
Topic archived. No new replies allowed.