【问题标题】:program works only when an integer is declared程序仅在声明整数时工作
【发布时间】:2014-02-17 05:15:12
【问题描述】:

我实际上是在尝试一些 C 编程代码并且我想出了这个程序,由于某种原因,它仅在声明整数并被赋予某些值时才有效。

下面的代码完美运行

#include<stdio.h>

int main()
{


    FILE *file = fopen("/proc/cpuinfo","r");
    char *line;
    int count = 0;
    if(file!=NULL)
    {
        while(fscanf(file," %[^\n]",line)!=-1)
        {
            printf("\n%s",line);
        }
        printf("\n\n\t* * * * * * * * * * * * * * * * * * * * * \n\n");
    }
    else
    {
        printf("\nFile Does not Exist\n");
    }
    return 0;
}

但这不起作用,(我的意思是,当我运行它时,我得到一个(null)值的无限循环。

#include<stdio.h>

int main()
{
    FILE *file = fopen("/proc/cpuinfo","r");
    char *line;

    if(file!=NULL)
    {
        while(fscanf(file," %[^\n]",line)!=-1)
        {
            printf("\n%s",line);
        }
        printf("\n\n\t* * * * * * * * * * * * * * * * * * * * * \n\n");
    }
    else
    {
        printf("\nFile Does not Exist\n");
    }
    return 0;
}

我正在使用 gcc 编译器

gcc -v

使用内置规范。 COLLECT_GCC=gcc COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.6/lto-wrapper 目标:x86_64-linux-gnu 配置:../src/configure -v --with-pkgversion='Ubuntu/Linaro 4.6.3-1ubuntu5' --with-bugurl=file:///usr/share/doc/gcc-4.6/README.Bugs --enable-languages=c,c++, fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.6 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.6 --libdir=/usr/lib --enable-nls --with-sysroot =/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --disable- werror --with-arch-32=i686 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux- gnu 线程模型:posix gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5)

谁能解释一下这里发生了什么,我想知道为什么会这样。

【问题讨论】:

  • “不起作用”的意思是……?
  • 我得到一个 (null) s 的无限循环。
  • 您正在访问一个未分配的指针。行为未定义。除此之外,没有 fclose。还有……
  • @deviantfan :但第一个工作完美,只有当我删除整数声明时它才工作。
  • 不,它一点也不完美。如果它(有时)有效,那只是运气。

标签: c linux gcc


【解决方案1】:

您没有为line 缓冲区分配内存,在您的情况下,这只是一个无效指针

在第一种情况下,你很幸运,因为指针指向一个可写区域(具体来说,你正在覆盖count所在的内存区域),但在第二种情况下,一个分段引发错误。

替换:

char *line; // Pointer to... somewhere?

与:

char line[4096];

或任何其他合适的缓冲区大小。如果您需要一个不适合堆栈的缓冲区,则将其声明为全局变量(强烈建议不要使用,除非您的应用程序非常小或您知道自己在做什么)或在堆上分配它,使用:

char *line = malloc(4096 * 1024);

并记得在不再需要缓冲区时调用free(line)(例如,在终止程序之前)。

【讨论】:

    【解决方案2】:
    char *line;
    

    应该是这样的

    char line[1024];
    

    并添加一个 fclose。

    因评论而编辑:
    如果你想要第一个定义和 malloc/free:

    char *line;
    line = malloc(1024);
    ...
    free(line);
    

    【讨论】:

    • 谢谢,使用数组是可行的,但是否可以使用指针来达到同样的效果?如果是,我想知道如何。
    • 数组变量的名字实际上是指向第一个元素的指针。
    • 基本上,您将指针传递给 fscanf。如果你想要更多的“指针”,请使用 malloc/free 自己分配 1024 个字节
    • @StefanoSanfilippo : 好的,我的意思是,如果我们使用一个固定大小的数组,如果行的大小比我们提供的大小大得多,如果我们使用大数组大小它就赢了'效率不高不是吗。
    • 因为你在阅读之前不知道行的大​​小,一旦你知道电流不够,你就必须得到一个更大的数组。有点复杂,因为您必须自己进行读取(而不是 fscanf)并处理整个内存。
    【解决方案3】:

    fscanf 写入由char *line; 指向的缓冲区,但 line 永远不会设置为指向任何有用的地方。大概添加额外的 int 会导致内存布局略有不同,因此它以不同的方式中断。

    【讨论】:

      【解决方案4】:

      更好的是,至少在 Linux 上,您可以使用 getline(3)

      int main() {
        FILE *file = fopen("/proc/cpuinfo","r");
        char *line=NULL;
        size_t linesiz= 0;
        ssize_t linelen= -1;
        if (file == NULL) { perror("/proc/cpuinfo"); exit (EXIT_FAILURE); };
        while ((linelen=getline(&line,&linesiz))>=0) 
          fputs(line,stdout);
        free(line), line=NULL;
        fclose(file);
      }
      

      然而,在实践中,我们都知道/proc/cpuinfo 包含一些长行(尤其是flags),但最长的行可能少于例如512 字节(在我的带有 Linux 3.13 内核的 i3770K 上,它有 483 字节)。知道这一点(不能完全保证,但今天确实如此,请参阅 proc(5))您可以简单地使用 fgets(3) 进行编码

      char linebuf[512];
      do {
        if (fgets(linebuf,sizeof(linebuf),file)==0) break;
        fputs(linebuf, stdout);
      } while(!feof(linebuf));
      

      注意feof(3) 应该在一些&lt;stdio.h&gt; 输入操作之后(而不是之前)使用(这里是fgets)。

      PS。不要忘记编译所有警告和调试信息(例如gcc -Wall -g)并使用调试器(gdb)。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-09-15
        • 1970-01-01
        • 1970-01-01
        • 2016-06-27
        • 1970-01-01
        • 1970-01-01
        • 2019-08-12
        相关资源
        最近更新 更多