我正在使用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起始地址读取每个内存位置?我不应该有权这样做吗?
答案 0 :(得分:3)
让我们看看这两个连续的行:
while(--argv > 0)
if((fp=fopen(*++argv,"r"))==NULL){
每次递减argv
时,最终会在下一行递增它。总的来说,你只是递减argv
,但实际上你从来没有读过argv
内存区域的边界。
即使您正在阅读argv
内存区域的边界,也就是undefined behavior,并且您无法保证会出现分段错误。您得到的结果取决于您的编译器,操作系统以及程序中的其他内容。
我怀疑执行--argv
也会给你未定义的行为,因为在执行该行之后,指针可能会指向为argv
数据分配的数组之外。但是,由于你指向那里时没有取消引用argv
,结果证明没问题。