首页 文章

程序仅在声明整数时起作用

提问于
浏览
0

我实际上正在尝试一些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版本4.6 . 3(Ubuntu / Linaro 4.6.3-1ubuntu5)

任何人都可以解释这里发生的事情,我想知道为什么会这样 .

4 回答

  • 2

    fscanf写入 char *line; 指向的缓冲区,但是线路永远不会设置为指向任何有用的位置 . 据推测,添加额外的int会导致内存布局略有不同,因此它会以不同的方式中断 .

  • 1
    char *line;
    

    应该是这样的

    char line[1024];
    

    并添加一个fclose .

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

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

    您没有为 line 缓冲区分配内存,在这种情况下,它只是 invalid pointer .

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

    更换:

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

    有:

    char line[4096];
    

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

    char *line = malloc(4096 * 1024);
    

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

  • 0

    更好的是,至少在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字节(在我的i3770K上使用Linux 3.13内核,它有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)应该在某些 <stdio.h> 输入操作(此处为 fgets )之后(而不是之前)使用 .

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

相关问题