首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >关于c程序中的myfopen()

关于c程序中的myfopen()
EN

Stack Overflow用户
提问于 2018-06-02 01:15:05
回答 1查看 197关注 0票数 -1

我的问题是关于这个问题:segmentation fault on c K&R fopen and fillbuf

在这个问题中,在myfopen()函数中,有一个循环;我不明白的是,fp的值是从_iob开始的,但是我不知道fp->标志在前三个值(已经固定)之后会取什么值。它们会取零值吗?还有一件事是,在答案中(参见下面的代码),他们说我们必须使用malloc来为fp提供内存空间,但fp已经提供了内存空间,因为主数组有空间,fp将继续获取数组元素的地址,所以还需要malloc吗?另外,如果所有元素都为零,那么在_iob ()函数中,for循环是否总是在fp =_iob+3?

  1. Secondly处中断,上面提到的模式是"r“,但是在write()之后使用的系统调用是possible?
  2. Thirdly,(),虽然它没有显示错误,但是为什么编译器在编译这段代码时不会显示错误或警告,而是显示一个对话框,说明"f_open.exe已停止工作”,即使我们编写malloc行(或不写),或者即使有"r“模式或"w”模式,这也保持不变。那么到底出了什么问题呢?

#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;}

提供的解决方案是:

代码语言:javascript
复制
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。

以下是您需要更改的内容。

代码语言:javascript
复制
myFILE *fp = (myFILE *)malloc(sizeof(myFILE));

要使用malloc,请务必使用#include。

另外,您的close函数应该在稍后释放()您的myFILE,以防止内存泄漏。

正如您所看到的,上面是对链接问题的答案:segmentation fault on c K&R fopen and fillbuf

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-02 03:01:12

其他问题中的诊断是假的

正如评论中所指出的,other question中的诊断是假的。特别是,myfopen()中的循环如下所示:

代码语言:javascript
复制
for (fp =_iob; fp <_iob + OPEN_MAX; fp++)
    if ((fp->flag & (_READ | _WRITE)) == 0)
        break;

是完全正确的。它遍历数组_iob的元素,并且永远不会遇到声明的空指针。针对前三个元素初始化缓冲区_iob;其余元素均为零。

故障的可能原因

此程序崩溃的最可能原因是:

  1. 没有为文件名提供参数。
  2. 无法打开所提供的名称进行读取。

main()显示的代码为:

代码语言:javascript
复制
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;
}

代码不会检查这些常见问题中的任何一个。它应该更像这样:

代码语言:javascript
复制
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() (直接或间接)调用的函数中。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50648250

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档