如何防止无限循环写入文件

时间:2013-10-18 04:05:37

标签: c

这是一个用于创建文件或目录副本的c代码,在fedora 19中使用gcc编译。它运行但不会停止,我可以看到创建的新文件大小不断增加。这段代码有什么问题?

#include<fcntl.h>
#include<stdio.h>
#include<unistd.h>

char buffer[2048];

int version = 1;

int main(int argc, char *argv[])
{
    void copy (int, int);

    int fdold, fdnew;

    if (argc != 3)
    {
        printf("insufficient arguments !!! \n");
        return (1);
    }

    fdold = open(argv[1], O_RDONLY);
    if (fdold == -1)
    {
        printf("cannot open file %s\n",argv[1]);
        return (1);
    }

    fdnew = creat(argv[2],0666);
    if (fdnew == -1)
    {
        printf("cannot create file %s\n",argv[2]);
        return (1);
    }

    copy (fdold, fdnew)

    return (0);
}

void copy (int fdold, int fdnew)
{
    int count;
    count = read(fdold, buffer, sizeof(buffer));

    while (count > 0)
        write(fdnew, buffer, count);
}

1 个答案:

答案 0 :(得分:5)

您永远不会更新count,并且您会一遍又一遍地写入相同的数据。在这段代码中:

count = read(fdold, buffer, sizeof(buffer));
while (count > 0)
    write(fdnew, buffer, count);

您从文件描述符读取一次,拉入count字节,当它大于0(可能是)时,您继续将缓冲区写入新文件。您永远不会从旧文件中读取更多数据。如果您可以看到文件变得越来越大,您也可以看到(取决于内容刷新到磁盘的方式)一遍又一遍地重复相同的内容。

你真正需要做的事情更像是这样:

while there is data to read from the old file
  read it into a buffer
  while there is data in the buffer to write to the new file
    write data from the buffer into the new file

稍微不那么伪编码,但是高度未经测试的形式,我认为你会找到类似这样的东西:

int count = 0;
int written;
while ( 0 < (count = read(fdold, buffer, sizeof(buffer))) ) {
  written = 0;
  while ( count > (written += write(fdnew, buffer+written, count-written))) );
}

外部循环确保您阅读,直到没有任何内容可供阅读,内部同时确保您致电write,直到writtencount一样大,即,直到你写完你读过的所有字节。这是“聪明”的代码,但它实际上太聪明了;你实际上需要检查written是否-1,否则你会开始做一些奇怪的事情。

更多错误检查,希望更具惯用性的东西可能是:

  for ( int count_in = -1; count_in != 0; ) {
    if ( -1 == (count_in = read(fd, buf, bufsize))) {
      perror("Problem reading from file");
      exit(-1);
    }
    else { 
      for ( int count_out = 0, out = 0; count_out < count_in; count_out += out ) {
        if ( -1 == (out = write(fd, buf+count_out, count_in-count_out)) ) {
          perror("Problem writing to file");
          exit(-1);
        }
      }
    }
  }