问题描述
我的问题与这个问题有关:分段错误在c K& R fopen和fillbuf 上.
My question is regarding this question: segmentation fault on c K&R fopen and fillbuf.
- 在这个问题上,在myfopen()函数中,有一个for循环;我不明白的是fp将具有从_iob开始的值,但我不知道在前三个值(已修复)之后fp-> flag会采用什么值.他们会取零值吗?还有一个问题是答案(请参见代码下方)中的错误内容是他们在说我们必须使用malloc为fp提供内存空间,但是fp已经提供了内存空间,因为_iob数组具有空间并且fp将继续获取数组元素的地址,因此malloc的需求是什么?如果所有元素均为零,那么for循环是否总是会在fp = _iob + 3处中断?
- 第二次在main()函数中,提到的模式为"r",但是后继使用的系统调用为write(),尽管它没有显示错误,但是为什么这可能呢?
-
第三,编译器不会在编译此代码时显示错误或警告,而是显示一个对话框,指出"f_open.exe已停止工作",即使我们编写了malloc行(或不编写,也没有变化) ),或者即使存在"r"模式或"w"模式.那怎么了?
- In this question, in myfopen() function, there is a for loop; what I don't understand is that fp will have value starting from _iob but I don't get what values will fp->flag take after the first three values(which have been fixed). Will they take zero values and one more thing is there that in the answers(see beneath the code) they are saying that we have to use malloc to provide memory space to fp but fp has already been provided memory space because _iob array has space and fp will keep on taking addresses of elements of arrays so what is the need of malloc?Also if all the elements are zero then will the for loop always break at fp =_iob+3?
- Secondly in main() function, the mode mentioned is "r" but the system call being used afterwords is write() although it does not show error but why is this possible?
Thirdly, the compiler does not show error or warning on compiling this code but shows a dialog box stating that "f_open.exe has stopped working" and this remains the same even if we write the malloc line(or without) or even if there is "r" mode or "w" mode. So what is wrong?
#include<fcntl.h>
#include<unistd.h>
#include<stdlib.h>
#define PERM 0644
#define EOF (-1)
#define BUFSIZE 1024
#define OPEN_MAX 20
typedef struct _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 _iob[OPEN_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[0])
#define stdout (&_iob[1])
#define stderr (&_iob[2])
#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)
return 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(char *name, char *mode)
{
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)
return NULL;
fp->fd = fd;
fp->cnt = 0;
fp->base = NULL;
fp->flag = (*mode=='r')? _READ : _WRITE;
return fp;
}
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;
}
提供的解决方案是:
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),因此您将取消引用空指针.繁荣.段故障.
When you reach the marked line, you try to dereference the fp pointer. Since it is (likely, but not certainly) initialized to zero (but I should say NULL), you are dereferencing a null pointer. Boom. Segfault.
这就是您需要更改的地方.
Here's what you need to change.
myFILE *fp = (myFILE *)malloc(sizeof(myFILE));
确保#include使用malloc.
Be sure to #include to use malloc.
另外,您的关闭函数以后也应该释放myFILE以防止内存泄漏.
Also your close function should later free() your myFILE to prevent memory leaks.
如您所见,以上是链接问题的答案:
As you can see the above is the answer given for the linked question: segmentation fault on c K&R fopen and fillbuf
推荐答案
另一个问题的诊断是虚假的
如评论中所述,其他问题中的诊断是虚假的.特别是,myfopen()
中的循环显示为:
Diagnosis in other question is bogus
As noted in the comments, the diagnosis in the other question is bogus. In particular, the loop in myfopen()
that reads:
for (fp =_iob; fp <_iob + OPEN_MAX; fp++)
if ((fp->flag & (_READ | _WRITE)) == 0)
break;
是完全正确的.它遍历数组_iob
的元素,并且永远不会遇到所声明的空指针.缓冲区_iob
为前三个元素初始化;其余全为零.
is perfectly correct. It iterates over the elements of the array _iob
, and never encounters a null pointer as claimed. The buffer _iob
is initialized for the first three elements; the remainder are all zeros.
此程序崩溃的最可能原因是:
The most likely causes of this program crashing are either:
- 没有为文件名提供参数.
- 提供的名称无法打开以供阅读.
显示为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;
}
该代码不检查这些常见问题中的任何一个.应该更像是:
The code does not check for either of these common problems. It should be more like:
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()
.
You have to add #include <string.h>
because this uses strlen()
. The error reporting via file descriptor I/O is clumsy, but this code precludes the use of the regular functions from <stdio.h>
. The program does include <stdlib.h>
so it would be possible to write exit(EXIT_FAILURE);
instead of return 1;
, but the net result is the same when the current function is main()
— though not in functions called (directly or indirectly) from main()
.
这篇关于关于c程序中的myfopen()的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!