使用feof()和fgetc()进行C分段错误错误

时间:2011-04-01 19:46:21

标签: c compiler-errors feof fgetc

任何人都可以帮助我解决我的困境吗?当我编译我的程序时,我没有得到任何错误或警告。但是,当我去实际运行可执行文件时,我得到了分段错误。如果我理解正确,就会发生这种情况,因为错误地使用了指针。我在feof(srcIn)行上得到一个特定的错误,我不知道为什么。除了程序开头的srcIn = fopen(argv [0],“r”)值之外,永远不会为FILE * srcIn分配新值。我最初使用C ++实现了这个解决方案,并且需要将其更改为C。无论如何,在C ++中,除了使用srcIn.eof()作为条件并使用srcIn.get(something)作为读取方法之外,我基本上做了相同的事情。它编译并运行没有任何问题。

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++;
}

编辑: 我忘了提到我在遇到seg故障时甚至没有真正进入主流。这让我相信可执行文件本身存在某种问题。 gdb告诉我seg错误发生在行: if(feof(srcIn)) 有什么想法吗?

4 个答案:

答案 0 :(得分:2)

我怀疑你的两个或四个字符的缩进不足以让你看到程序的真实范围;它可能就像@mu太短而且@Null Set指出的那样简单,当你的意思是argv[0]时你得到argv[1],它可能就像@Lou Franco指出的那样你'写完你的数组的结尾,但这段代码确实闻起来很有趣。这是您的代码,通过Lindent运行以获得更大的标签和每行一个语句:

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++;
}

您正在if语句中检查是否已在顶部的文件末尾读取,但您再也不会检查eof。决不。当您从while()循环中的输入中读取时,使用'\n'作为退出条件,如果字符高于' '则打印输出,如果您读取{{{},请执行一些制表符展开1}},您忘记处理来自'\t'的{​​{1}}返回。如果您的输入文件没有EOF,则此程序可能会将fgetc(3)写入'\n'数组,直到您出现段错误。如果您的输入文件没有直接在-1上结束,那么此程序可能会将line写入'\n'数组,直到您发生段错误。

从输入流中读取一个字符并对其进行操作的大多数循环都是这样写的:

-1

检查line的输入。如果可以的话,只从一个地方读取输入。使用一个表或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; } } / EOF / if / else if树来决定如何处理输入字符。最初使用else if成语可能不自然,但在C中很常见。

随意为您自己的代码窃取我建议的循环格式,并弹出复杂的标签扩展代码。看起来你做对了,但我对此并不积极,我不希望它分散注意力循环的整体风格。我认为你会发现扩展我的代码来解决你的问题比让你的工作更容易。 (我完全希望你可以,但我认为维护它并不好玩。)

答案 1 :(得分:1)

argv[0]是您的计划的名称,因此您的fopen(argv[0], 'r')可能会失败。我猜你想要打开argv[1]。当然,在尝试使用其返回值之前,请检查fopen是否成功。

答案 2 :(得分:1)

它可能不在这个功能中,但如果问题出现在这里,我最担心的是在线超出界限。你写的不仅仅是maxLineLength个字符吗?您应该在进行索引之前进行检查。

编辑:您似乎对这个错误甚至意味着什么感到困惑 - 我会尝试清理它。

当您遇到分段错误时,它所发生的行就是最终检测到内存已损坏的代码行。它不一定与真正的问题有任何关系。你需要做的是首先找出腐败发生的地方。

很常见的原因:

  1. 多次拨打免费或删除指针
  2. 在指针上调用错误的删除(删除或删除[])
  3. 使用未初始化的指针
  4. 在空闲或删除后使用指针
  5. 走出阵列的边界(这就是我认为你做的)
  6. 投射指向错误类型的指针
  7. 执行reinterpret_cast,其中目标类型无法正确重新解释
  8. 使用不正确的调用约定调用函数
  9. 保留指向临时对象的指针
  10. 还有很多其他方法。

    解决这个问题的关键是

    1. 假设您的代码错误
    2. 通过代码路径中的检查(如果简短)来查找这些类型的问题
    3. 使用可以告诉您在执行此操作的代码行中存在这些问题的工具
    4. 意识到发生分段错误的代码行不一定是错误。

答案 3 :(得分:1)

它可能应该是srcIn = fopen(argv[1], "r")。 main获取的0字符串参数通常是程序的名称,1 st参数是您传递给程序的第一个命令行参数。