return 变量初始化时,读取缓冲区清零

Read buffer is zero'd out when return variable is initialised

这是一个真正的 WTF 情况...我要疯了吗!?

我注意到在更新我的代码以停止我的 linter 抱怨后,我的 FUSE 读取操作开始用零填充缓冲区:

int cramp_read(const char* path, char* buf, size_t size, off_t offset, struct fuse_file_info* fi) {
  int res = 0;

  struct my_filep* f = get_filep(fi);
  (void)path;

  if (f) {
    switch (f->type) {
      case fd_normal:
        if (pread(f->filep, buf, size, offset) == -1) {
          res = -errno;
        }
        break;

      case fd_special:
        if (my_read(f->specialp, buf, size, offset) == -1) {
          res = -errno;
        }
        break;

      default:
        res = -EPERM;
    }
  } else {
    res = -EBADF;
  }

  return res;
}

也就是说,特别是 pread 分支(我还没有写 my_read)。然而,调试显示 pread 正确地将缓冲区设置为文件内容......经过一番挖掘,我发现错误是在我初始化变量时:也就是说, int res = 0; 似乎是造成这个的原因行为。如果我将其改回 int res;,它会再次开始工作。

更奇怪的是:当我让变量未初始化并在最后一个 return 之前将其打印到 stderr 时——即,在完成所有工作之后——pread 失败我收到 EPERM 错误。

有人可以解释一下这是怎么回事吗?应我的 linter 的要求,我已经在别处初始化了我的变量,现在我担心我引入了一大堆等待被发现的定时炸弹!

好吧,我是个白痴!阅读 FUSE 文档后,我发现 read 实现应该 return 读取字节数,而不是通常的 FUSE 接口 0 表示成功,-errno 表示失败。

以下解决了问题,同时保留了初始化:

...
if ((res = pread(f->filep, buf, size, offset)) == -1) {
...

(对于我尚未实现的 my_read 分支也是如此。)