【问题标题】:Using fwrite without calling fflush or writing to stderr first在不调用 fflush 或先写入 stderr 的情况下使用 fwrite
【发布时间】:2013-06-26 06:41:21
【问题描述】:

我有一个将二进制数据写入文件或stdout 的函数。然而,对fwrite() 的调用有时会失败,除非我在尝试fwrite 之前fflush(stderr) 或向stderr 打印报告。

这是正常行为,还是表明存在一些潜在的内存问题?调试起来很困难,因为一旦我将fprintstderr 的数据我尝试将fwritestdout 的数据,“问题”就消失了。

这是该函数的一个非常简化的版本。

int writebinary(FILE *fpout, void *data, long ntowrite) {

    long i; 

    /* lets say we know the input data is double float */
    double *p = data; 

    /* including this test line makes the function work! */
    for(i=0; i<ntowrite;i++) fprintf(stderr,"data[%d]=%g\n",i,p[i]);

    /* attempt to write data[] as a single block of bytes */
    m= fwrite(data,(size_t)(ntowrite*sizeof(double)),1,fpout);

    if(m!=1) {
        fprintf(stderr,"Write error: %d\n",ferror(fpout));
        return(-1); 
    }
    else return(m);
}

任何智慧都值得赞赏:)

【问题讨论】:

  • 你有示例代码吗?
  • 提供任何示例代码让我们的工作变得轻松
  • 它嵌入在一些非常复杂的代码中——希望能省去你的细节——让我先检查一下 errno....
  • 我看到一个程序崩溃,除非您启用日志记录。事实证明,日志库使用了信号量,从而防止了两个线程之间的竞争条件。 stderr 写入是同步发生的,因此您的代码可能处于类似情况。
  • OT:... = fwrite(data, sizeof(double), (size_t) ntowrite, fpout); 不是更直截了当吗?

标签: c fwrite stderr printf fflush


【解决方案1】:

这不是正常行为。
推荐以下。帖子中有许多值得关注的事情(见下文),但并未指出问题所在 - 但有些事情是错误的。

int writebinary2(FILE *fpout, void *data, long ntowrite) {
  size_t n = (size_t) ntowrite;
  double *dp = (double *) data;
  // pedantic checks
  if ((!fpout) || (!data) || (dp != data) || (ntowrite <= 0) || (n != ntowrite)) {
    fprintf(stderr,"Bad parameter\n");
    return(0);
  }
  clearerr(stderr);  // only needed for debug
  clearerr(fpout);
  /* attempt to write blocks of doubles */
  size_t m = fwrite(dp, sizeof(double), n, fpout);
  if (m != n) {
    fprintf(stderr,"Write error: %d\n",ferror(fpout));
    clearerr(fpout);
    return(-1);
  }
  if (fflush(fpout)) {
    fprintf(stderr,"Flush error: %d\n",ferror(fpout));
    clearerr(fpout);
    return(-1);
  }
  return(1);
}
  1. ntowrite s/b size_t,一个无符号整数。 ntowrite = 0 可能会导致 m 混淆。 ntowrite 将导致问题。
  2. m 未声明,假定为 size_t。
  3. format "data[%d]=%g\n" s/b "data[%ld]=%g\n"
  4. i s/b size_t.
  5. (size_t)(ntowrite*sizeof(double)) s/b ((size_t)ntowrite)*sizeof(double)。请参阅 #7。
  6. fprintf(stderr... 应该不需要。这是的问题。
  7. 即使size * n 溢出,fwrite(..., size, n ...) 也可以工作。比 OP 更安全。

【讨论】:

    猜你喜欢
    • 2020-06-16
    • 2017-07-28
    • 2015-01-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多