我的问题是关于这个问题:segmentation fault on c K&R fopen and fillbuf。
在这个问题中,在myfopen()函数中,有一个循环;我不明白的是,fp的值是从_iob开始的,但是我不知道fp->标志在前三个值(已经固定)之后会取什么值。它们会取零值吗?还有一件事是,在答案中(参见下面的代码),他们说我们必须使用malloc来为fp提供内存空间,但fp已经提供了内存空间,因为主数组有空间,fp将继续获取数组元素的地址,所以还需要malloc吗?另外,如果所有元素都为零,那么在_iob ()函数中,for循环是否总是在fp =_iob+3?
#include #include #include #define PERM 0644 #define EOF (-1) #define BUFSIZE 1024 #define OPEN_MAX 20类型定义结构_iobuf{ int cnt;char *ptr;char *base;int flag;int fd;} myFILE;enum _flags { _READ = 01,_WRITE = 02,_UNBUF = 04,_EOF = 010,_ERR = 020 };myFILE _iobOPEN_MAX={ {0,(char *) 0,(char *) 0,_READ,0 },{0,(char *) 0,(char *) 0,_WRITE,1 },{0,(char *) 0,(char *) 0,_WRITE | _UNBUF,2} };#define stdin (&_iob) #define stdout (&_iob1) #define stderr (&_iob2) #define getc(p) ( --(p)->cnt>=0?(unsigned char) *(p)->ptr++:_fillbuf(p) ) int _fillbuf(myFILE *fp) { int bufsize;if(fp->flag& (_READ|_EOF|_ERR))!=_READ) return EOF;bufsize=(fp->flag & _UNBUF)?1: BUFSIZE;if(fp->base==NULL) if((fp->base=(char *)malloc(bufsize))==NULL)返回EOF;fp->ptr=fp->base;fp->cnt=read(fp->fd,fp->ptr,bufsize);if(--fp->cnt<0){ if(fp->cnt == -1) fp->flag |= _EOF;else fp->flag |= _ERR;return EOF;} return (unsigned char) *fp->ptr++;} myFILE *myfopen(字符*名称,字符*模式){ int fd;myFILE *fp;if(*mode!='r‘&& *mode!='w’&& *mode!='a') return NULL;for(fp=_iob;fp<_iob+OPEN_MAX;fp++) if((fp->flag & (_READ | _WRITE))==0) break;if(fp>=_iob+OPEN_MAX) return NULL;if(*mode=='w') fd=creat(name,PERM);else if(*mode=='a'){ if((fd=open(name,O_WRONLY,0))==-1) fd=creat(name,PERM);lseek(fd,0L,2);} else fd=open(name,O_RDONLY,0);if(fd==-1)返回NULL;fp->fd = fd;fp->cnt = 0;fp->base = NULL;fp->标志= (*mode=='r')?_READ:_WRITE;return fp;} int main(int argc,char *argv[]) { myFILE *fp;int c;if((fp=myfopen(argv1,"r"))!=NULL) write(1,“打开的\n”,sizeof(“打开的\n”));while((c=getc(fp))!=EOF) write(1,&c,sizeof(c));return 0;}
提供的解决方案是:
myFILE *fp;
if(*mode!='r' && *mode!='w' && *mode!='a')
return NULL;
for(fp=_iob; fp<_iob+OPEN_MAX; fp++)
if((fp->flag & (_READ | _WRITE))==0) // marked line
break;
当您到达标记的行时,您尝试取消对fp指针的引用。由于它(很可能,但不一定)被初始化为零(但我应该说是NULL),您将取消对null指针的引用。轰隆隆。Segfault。
以下是您需要更改的内容。
myFILE *fp = (myFILE *)malloc(sizeof(myFILE));
要使用malloc,请务必使用#include。
另外,您的close函数应该在稍后释放()您的myFILE,以防止内存泄漏。
正如您所看到的,上面是对链接问题的答案:segmentation fault on c K&R fopen and fillbuf
发布于 2018-06-02 03:01:12
其他问题中的诊断是假的
正如评论中所指出的,other question中的诊断是假的。特别是,myfopen()
中的循环如下所示:
for (fp =_iob; fp <_iob + OPEN_MAX; fp++)
if ((fp->flag & (_READ | _WRITE)) == 0)
break;
是完全正确的。它遍历数组_iob
的元素,并且永远不会遇到声明的空指针。针对前三个元素初始化缓冲区_iob
;其余元素均为零。
故障的可能原因
此程序崩溃的最可能原因是:
为main()
显示的代码为:
int main(int argc, char *argv[])
{
myFILE *fp;
int c;
if((fp=myfopen(argv[1], "r"))!=NULL)
write(1, "opened\n", sizeof("opened\n"));
while((c=getc(fp))!=EOF)
write(1, &c, sizeof(c));
return 0;
}
代码不会检查这些常见问题中的任何一个。它应该更像这样:
int main(int argc, char *argv[])
{
myFILE *fp;
int c;
if (argc != 2)
{
static const char usage[] = "Usage: mystdio filename\n";
write(2, usage, sizeof(usage)-1);
return 1;
}
if ((fp = myfopen(argv[1], "r")) == NULL)
{
static const char filenotopened[] = "mystdio: failed to open file ";
write(2, filenotopened, sizeof(filenotopened)-1);
write(2, argv[1], strlen(argv[1]));
write(2, "\n", 1);
return 1;
}
write(1, "opened\n", sizeof("opened\n"));
while ((c = getc(fp)) != EOF)
write(1, &c, sizeof(c));
return 0;
}
您必须添加#include <string.h>
,因为它使用strlen()
。通过文件描述符I/O进行的错误报告很笨拙,但此代码排除了从<stdio.h>
中使用常规函数的可能性。该程序确实包含<stdlib.h>
,因此可以编写exit(EXIT_FAILURE);
而不是return 1;
,但是当当前函数为main()
时,最终结果是相同的-尽管不是在从main()
(直接或间接)调用的函数中。
https://stackoverflow.com/questions/50648250
复制相似问题