Segmentation Fault using fprintf (really weird)

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • spiralfire
    New Member
    • Nov 2009
    • 8

    Segmentation Fault using fprintf (really weird)

    I wrote a translator, that reads a DIMACS graph format and writes to a simpler format...

    basically DIMACS format is:

    Code:
    c  comment
    
    p type nodes edges    //type is alwats edge on my problems, nodes is the number of nodes and edges number of edges
    
    e v1 v2   //this means an edge connecting v1 and v2, both integers
    this is the file im using:

    Code:
    c FILE: miles500.col
    c Translated from Stanford GraphBase File: miles500.gb
    c Stanford GraphBase ID: miles(128,0,0,0,500,127,0)
    p edge 128 2340
    e 1 120
    e 1 110
    ..... (many many many edges here)
    e 128 8
    e 128 7
    the output i want is:

    Code:
    nodes edges
    v1 v2
    ...
    the code is this one:
    in was opened with "r"
    out was opened with "w+"
    both were checked if null

    Code:
    char line[400];
    
    	char* token;
    	while( !feof(in))
    	{
    		fgets(line, 399, in);
    		if(line[0] == 'p')
    		{
    			int nodes, edges;
    			strtok(line, " ");
    			token = strtok(NULL, " ");
    
    			token = strtok(NULL, " ");
    			nodes = atoi(token);
    
    			token = strtok(NULL, " ");
    			edges = atoi(token);
    			fprintf(out, "%d %d\n", nodes, edges);
    		}
    		else if(line[0] == 'e')
    		{
    			int v1, v2;
    			strtok(line, " ");
    			
    			token = strtok(NULL, " ");
    			v1 = atoi(token);
    
    			token = strtok(NULL, " ");
    			v2 = atoi(token);
    
    			fprintf(out, "%d %d\n", v1, v2);
    		}
    	}

    ant it works well..

    but for some reason, after writing a lot of edges it sends me a segmentation fault..

    original file is:


    in the output file i have:
    Code:
    128 2340
    1 120
    1 110
    1 109
    ... keeps writing ok
    111 84
    111 75
    thats not all of the original files edges, its like more than a half..

    then SEGMENTATION FAULT.. and aborts

    what could be happening? some kind of writing limit?
  • jfwfmt
    New Member
    • Nov 2009
    • 12

    #2
    I believe you are probably reading a line from your input file that is missing a token.

    Try checking the token value for NULL before passing it to atoi(), then printing a error message and exit. If this shows up a problem, I'd then count input lines as I read them in and print the line number as part of the error message, this will make it easier to find the bad line in the input file.

    Checking for NULL is good defensive programming even if "it can't happen".

    Good Luck

    /s/ Jim WIlliams

    Comment

    • RRick
      Recognized Expert Contributor
      • Feb 2007
      • 463

      #3
      Your feof doesn't work right.

      jfwfmt is right, you are reading a blank line from the end of the file and this is causing your program to blow up.


      fgets stops when it runs into "either" an eof or a <cr>. In your case, fgets stops just before the eof when it reads the last line. The next time around, feof says there is still something in the file, but fgets reads nothing into line. Also, the line buffer has some left over info from the previous strtoks. This gets you to the "e" condition, but blows up on atoi.

      Your output file is incomplete, because data is buffered for file output. When your program blows up, the file data in the buffer is thrown away. Put a printf in the "e" condition code and you'll see that you are reading to the end of the input file.


      You have a couple of choices to fix the problem. Since fgets returns the number of bytes read, the simplest solution is to check that fgets actually reads something. If not, then exit the loop.

      Comment

      • spiralfire
        New Member
        • Nov 2009
        • 8

        #4
        Originally posted by RRick
        jfwfmt is right, you are reading a blank line from the end of the file and this is causing your program to blow up.


        fgets stops when it runs into "either" an eof or a <cr>. In your case, fgets stops just before the eof when it reads the last line. The next time around, feof says there is still something in the file, but fgets reads nothing into line. Also, the line buffer has some left over info from the previous strtoks. This gets you to the "e" condition, but blows up on atoi.

        Your output file is incomplete, because data is buffered for file output. When your program blows up, the file data in the buffer is thrown away. Put a printf in the "e" condition code and you'll see that you are reading to the end of the input file.


        You have a couple of choices to fix the problem. Since fgets returns the number of bytes read, the simplest solution is to check that fgets actually reads something. If not, then exit the loop.
        That's a really probable issue.. but the thing is i just finished my code, and it some files work, others don't. They are exactly the same in the end of file, no blank line, just the last edge and nothing else, i just can't figure out why this happen.

        edit: forgot to say something.. i left the idea of reading an DIMACS file and writing in a simpler format, i now just read the input from the DIMACS file, and it stills send me an error. I tried checking for null tokens, and in the 2 last lines of the file the second token (not the "e", but the first int) gets null and I don't call the atoi.. segmentation fault was solved, the problem now is in the package we are using (GLPK), that just aborts it's execution with no error message, and that just sucks.

        Thanks for the replies.

        Comment

        • RRick
          Recognized Expert Contributor
          • Feb 2007
          • 463

          #5
          Check for &lt;cr&gt; at the end of the file

          Watch out, there could be a subtle difference between the files that work and the files that don't work.

          The original crash and burn problem was caused by the last character in the file being a <cr> (i.e. a carriage return).

          If there is no <cr> after the last entry in the file, then the current code will work just fine.

          Comment

          Working...