编译时没有分段错误

时间:2015-01-29 17:59:37

标签: c linux

我正在使用K& R的示例,它是一个用于查看文件的cat实用程序

#include <stdio.h>

main(int argc,char **argv){
      FILE *fp;
      void filecopy(FILE *,FILE *);

      if(argc==1)
           filecopy(stdin,stdout);
      else                           // accidentally mistyped
           while(--argv > 0)         // should have been --argc > 0
                if((fp=fopen(*++argv,"r"))==NULL){
                        printf("cat: can't open %s\n",*argv);
                        return 1;
                }else{
                        filecopy(fp,stdout);
                        fclose(fp);
                }
     return 0;
}
void filecopy(FILE *ifp,FILE *ofp)
{
      int c;
      while((c=getc(ifp))!=EOF)
            putc(c,ofp);
}

使用gcc cat.c编译时, 当我从终端运行./a.out cat.c时,我得到的只是一些chinnesse符号和一些可读的文本(如_fini_array _,_ GLOBAL_OFFSET_TABLE_等等......),垃圾一直持续到我按下Ctrl + C ,我想问为什么我没有遇到分段错误,因为程序没有从argv起始地址读取每个内存位置?我不应该有权这样做吗?

1 个答案:

答案 0 :(得分:3)

让我们看看这两个连续的行:

    while(--argv > 0)
            if((fp=fopen(*++argv,"r"))==NULL){

每次递减argv时,最终会在下一行递增它。总的来说,你只是递减argv,但实际上你从来没有读过argv内存区域的边界。

即使您正在阅读argv内存区域的边界,也就是undefined behavior,并且您无法保证会出现分段错误。您得到的结果取决于您的编译器,操作系统以及程序中的其他内容。

我怀疑执行--argv也会给你未定义的行为,因为在执行该行之后,指针可能会指向为argv数据分配的数组之外。但是,由于你指向那里时没有取消引用argv,结果证明没问题。