开发者

C segmentation fault errors with feof() and fgetc()

Can anyone help me solve my dilemma? When I compile my program I get no errors or warnings. When I go to actually run the executable, though, I get a segmentation error. If I'm to understand correctly, this happens because a pointer is in short being used incorrectly. I get a specific error on the feof(srcIn) line and I'm not sure why. The FILE* srcIn is never assigned a new value aside from the srcIn = fopen(argv[0], "r") value at the beginning of the program. I had originally had this solution implemented in C++ and needed to changed it to C for reasons. Anyways, in the C++ one I did essentially the same exact thing except using srcIn.eof() as the the condition and srcIn.get(something) as the reading method. and it compiled and ran without any problems.

int chara;
int line[maxLineLength+1];

void nextch(void){
    const int charPerTab = 8;
    if(charCounter == charLineCounter){
      if(feof(srcIn)){
          printf("\n");
          isEOF = TRUE;
          return;
      }

      printf("\n"); lineCounter++;
      if(chara != '\0'){ printf("%c", line[charLineCounter-1]); } // first character each line after the first line will be skipped otherwise
      charLineCounter = 0; charCounter = 0;
      while(chara != '\n'){
         chara = fgetc(srcIn);
         if(chara >= ' '){
            printf("%c", chara);
            line[charLineCounter] = chara; charLineCounter++;
         }
         else if(chara == '\t'){  // add blanks to next tab
            do{ printf(" "); line[charLineCounter] = ' '; charLineCounter++; }
            while(charLineCounter % charPerTab != 1);
         }
      }
      printf("\n"); line[charLineCounter] = chara; charLineCounter++; l开发者_运维百科ine[charLineCounter] = fgetc(srcIn); charLineCounter++;
                                                                      // have to get the next character otherwise it will be skipped
   }
   chara = line[charCounter]; charCounter++;
}

EDIT: I forgot to mention that I'm not even actually going into main when I get the seg fault. This leads me to believe that the executable itself has some sort of problem. gdb tells me the seg fault is happening at line: if(feof(srcIn)) Any ideas?


I've got a haunting suspicion that your two-or-four-character indents aren't sufficient to let you see the real scope of the program; it could be as easy as @mu is too short and @Null Set point out, that you've got an argv[0] when you meant argv[1], and it could be as @Lou Franco points out and you're writing past the end of your array, but this code sure smells funny. Here's your code, run through Lindent to get larger tabs and one-statement-per-line:

int chara;
int line[maxLineLength + 1];

void nextch(void)
{
    const int charPerTab = 8;
    if (charCounter == charLineCounter) {
            if (feof(srcIn)) {
                    printf("\n");
                    isEOF = TRUE;
                    return;
            }

            printf("\n");
            lineCounter++;
            if (chara != '\0') {
                    printf("%c", line[charLineCounter - 1]);
            }               // first character each line after the first line will be skipped otherwise
            charLineCounter = 0;
            charCounter = 0;
            while (chara != '\n') {
                    chara = fgetc(srcIn);
                    if (chara >= ' ') {
                            printf("%c", chara);
                            line[charLineCounter] = chara;
                            charLineCounter++;
                    } else if (chara == '\t') {     // add blanks to next tab
                            do {
                                    printf(" ");
                                    line[charLineCounter] = ' ';
                                    charLineCounter++;
                            }
                            while (charLineCounter % charPerTab != 1);
                    }
            }
            printf("\n");
            line[charLineCounter] = chara;
            charLineCounter++;
            line[charLineCounter] = fgetc(srcIn);
            charLineCounter++;
            // have to get the next character otherwise it will be skipped
    }
    chara = line[charCounter];
    charCounter++;
}

You're checking whether or not you've read to the end of the file at the top, in an if statement, but you never check for eof again. Never. When you read from input in your while() loop, you use '\n' as your exit condition, print the output if the character is above ' ', do some tab expansion if you read a '\t', and you forgot to handle the EOF return from fgetc(3). If your input file doesn't have an '\n', then this program will probably write -1 into your line array until you segfault. If your input file does not end directly on a '\n', this program will probably write -1 into your line array until you segfault.

Most loops that read one character from an input stream and operate on it are written like this:

int c;
FILE *f = fopen("foo", "r");

if (!f) {
    /* error message if appropriate */
    return;
}

while ((c=fgetc(f)) != EOF) {
    if (' ' < c) {
        putchar(c);
        line[counter++] = c;
    } else if ('\t' == c) {
        /* complex tab code */
    } else if ('\n' == c) {
        putchar('\n');
        line[counter++] = c;
    }
}

Check the input for EOF. Read input from only one spot, if you can. Use one table or if/else if/else if/else tree to decide what to do with your input character. It might not come natural to use the array[index++] = value; idiom at first, but it is common in C.

Feel free to steal my suggested loop format for your own code, and pop in the complex tab expansion code. It looked like you got that right, but I'm not positive on that, and I didn't want it to distract from the overall style of the loop. I think you'll find extending my code to solve your problem is easier than making yours work. (I fully expect you can, but I don't think it'd be fun to maintain.)


argv[0] is the name of your program so your fopen(argv[0], 'r') is probably failing. I'd guess that you want to open argv[1] instead. And, of course, check that the fopen succeeds before trying to use its return value.


It should probably be srcIn = fopen(argv[1], "r") instead. The 0th string parameter your main gets is normally the name of the program, and the 1st parameter is the first command line paramter you passed to the program.


It might not be in this function, but if the problem is here, I'd be most suspect of going out of bounds on line. Are you ever writing more than maxLineLength characters? You should put a check before you ever index into line.

Edit: You seem to be confused about what this error even means -- I will try to clear it up.

When you get a segmentation fault, the line that it happens on is just the line of code where it was finally detected that you have corrupted memory. It doesn't necessarily have anything to do with the real problem. What you need to do is to figure out where the corruption happened in the first place.

Very common causes:

  1. calling free or delete on a pointer more than once
  2. calling the wrong delete on a pointer (delete or delete[])
  3. using an uninitialized pointer
  4. using a pointer after free or delete was called on it
  5. going out of bounds of an array (this is what I think you did)
  6. casting a pointer to a wrong type
  7. doing a reinterpret_cast where the target type cannot be reinterpreted correctly
  8. calling functions with improper calling conventions
  9. keeping a pointer to a temporary object

And there are many other ways.

The key to figuring this out is to

  1. assume that your code is wrong
  2. look for these kinds of problems by inspection in the code path (if short)
  3. use tools that can tell you that you have these problems at the line of code where you did it
  4. realizing that the line of code where the segmentation fault happens is not necessarily the bug.
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜