C++ 和系统调用:忽略返回值并检查 errno

问题描述 投票:0回答:1

C 中的错误检查是一项非常冗长的任务,并且使代码不可读。在 C++ 中也有例外,但是当我使用 C++ 调用 C 函数时,头痛又回来了。我希望有一个“C++ 的系统调用包装器”,其中所有函数都具有相同的名称和参数,但错误会转化为异常,仅此而已。这将改变游戏规则。

尝试解决与 C++ 中的 C 函数/系统调用交互时的冗长问题,我提出了以下解决方案(此处进行了简化):

void ko(char const* doingwhat) // or ko_check or whatever
{
   if (errno != 0)
      throw std::runtime_error(doingwhat);
}

void some_method()
{
    errno = 0;
    int fd = open(blablabla, blablabla); ko("opening the file");
    void* ptr = mmap(blablabla, blablabla); ko("mmaping it");
    
    struct stat st; fstat(fd, &st); ko("getting stats");
    // etc etc etc
}

方法是直接忽略返回值,改为检查errno。由于

errno
是线程本地的,并且只有在 libc 调用中出现错误时才能更改,因此在方法开头设置 errno = 0 就足够了。

在 C 中,这样做是毫无意义的(或者至少没有那么有益),因为无论如何你都无法摆脱在错误情况下返回的情况,这就是为什么我认为我从未在任何有关错误处理的讨论中看到过这种方法。

我的方法有什么重要的陷阱吗?在令人惊讶的情况下,

errno
可以成为
!= 0
吗?有什么需要注意的吗?事实上,我从未在任何地方看到过这种“方法”的讨论,这让我想知道是否有任何充分的理由,因为我没有看到任何理由。

注意: 当然,您必须小心那些在可能适合您的条件下设置

errno
的函数。非常了解您使用的功能,不要让只调用
ko
的习惯导致您忘记不断检查您使用的功能的
man
页面。

c++ c libc
1个回答
0
投票

用 C++ 包装 C 时,不能用异常代替错误检查。 根据 (草案)C11 标准 7.5 错误

<errno.h>
,第 3 段

初始线程中的 errno 值在程序启动时为零(其他线程中的 errno 初始值为不确定值),但从未被任何库函数设置为零。 errno 的值可以通过库函数调用设置为非零,无论是否存在错误,前提是本国际标准中的函数描述中未记录 errno 的使用。

注意这两条语句:

[

errno
] ...任何库函数都不会设置为零。

和。

无论是否存在错误,库函数调用都可以将

errno
的值设置为非零,前提是本国际标准中的函数描述中未记录
errno
的使用。

因此,您永远不能依赖

errno
的值,除非您已经确定已从记录为设置
errno
的函数收到错误。

因此,您必须用 C++ 调用来包装所有 C 调用以正确处理错误的方式,以便将它们转换为异常。

没关系,依靠异常来处理预期的条件是被广泛认为是非常不好的做法。 所有文件结束 - 在 EOF 上抛出异常是对异常的滥用 - 它绝不是例外

© www.soinside.com 2019 - 2024. All rights reserved.