我的库应该处理坏指针输入的SIGSEGV吗?

12

我正在编写一个小型库,以FILE *指针作为输入。

如果我立即检查这个FILE *指针并发现它导致了一个段错误,是更正确的处理信号,设置errno并正常退出;还是不做任何处理,并使用调用者安装的信号处理程序,如果他有的话?

普遍认为“库不应该导致崩溃”。但我的想法是,由于这个特定的信号肯定是调用者的错误,那么我不应该试图向他隐藏这些信息。他可能已经安装了自己的处理程序来以自己的方式对问题做出反应。同样的信息可以通过errno获得,但是SIGSEGV的默认处理方式有很好的原因,通过将信号传递给上层让调用者处理他自己的错误或崩溃并保护他免受进一步的损害,从而尊重这种哲学。

您是否同意这种分析,或者您是否认为在这种情况下处理SIGSEGV有一些令人信服的理由?


2
据我所知,标准C库不处理内部崩溃,为什么你的库要处理呢?不过我猜这取决于你打算用你的库做什么。(顺便问一下,对FILE *的检查如何导致SIGSEV?只是好奇) - BigMike
6个回答

7
控制处理程序不是库的业务,我认为除非明确要求,否则这样做有些冒犯。为了最小化崩溃,库可能会在一定程度上验证其输入。超出此范围的:垃圾输入 - 垃圾输出。

5

普遍的看法似乎是“库永远不应该导致崩溃”。

我不知道你从哪里得到这个看法的 - 如果它们传递了无效指针,你应该崩溃。任何库都会。


有趣的是,虽然您的说法对大多数函数来说是正确的,但也有一些例外。例如,write和getline分别会以EBADF和EINVAL退出。 - User123abc
抱歉,对于写入操作来说这是EFAULT错误,尽管它也会检查EBADF错误。 - User123abc
@User123abc,您确定在谈论无效指针时不只是空指针吗? - Michael Krelin - hacker

3

如果检查到一个NULL指针,那么我认为进行检查是合理的。但除此之外,如果他们传递了垃圾数据,则违反了函数的约定,会导致程序崩溃。


2

这是一个主观问题,可能不适合在SO上讨论,但我会陈述一下我的意见:

从这样的角度考虑:如果你有一个函数,它接受以空字符结尾的char *字符串,并且已经有相应的文档说明,但调用者传递了没有空字符终止符的字符串,你是应该捕获信号并批评调用者呢?还是让程序崩溃,并让使用你API的糟糕程序员自己修复代码呢?

如果你的代码需要一个FILE *指针,并且你的文档说“传递任何已打开的FILE *”,但他们传递了一个关闭或失效的FILE *对象,他们已经违反了契约。检查这种情况会减慢那些正确使用你库的人的代码,以适应那些不正确使用你库的人,而让程序崩溃将保持最快速度的代码供那些阅读文档并编写良好代码的人使用。

你是否期望那些传递无效FILE *指针的人检查并正确处理错误?还是他们更可能盲目地继续执行代码,导致稍后再次崩溃,这种情况下处理此崩溃可能只是掩盖了错误?


1
此外,没有理由期望能够捕获传递无效 FILE * 的情况。这完全取决于系统的实现和内部行为。一个无效的 FILE * 可能会看起来“正常”,但实际上可能会执行完全错误的操作,甚至破坏您的库代码并防止其检查工作(在没有内存保护的系统上)。 - R.. GitHub STOP HELPING ICE

1
内核如果收到错误指针不应该崩溃,但库可能会。这并不意味着您不应该进行错误检查;一个好的程序在面对不合理的坏数据时立即停止运行。我更喜欢库调用assert(f != NULL)而不是继续执行并最终解引用NULL指针。

-1

抱歉,但是认为库应该崩溃的人只是懒惰(也许是考虑时间和开发工作)。库是函数的集合。库代码不应该“只是崩溃”,就像软件中的其他函数不应该“只是崩溃”一样。

当然,如果涉及多种语言或(相对)奇特的语言特性(如异常),库可能会有一些关于如何在API边界传递错误的问题,但这并没有什么太特别的地方。实际上,这只是编写库的负担之一,而不是应用程序代码。

除非你真的无法证明开销,否则每个系统之间的接口都应该实现健全性检查,或者更好的是按照契约设计,以防止安全问题和错误。

有许多处理此问题的方法,您应该优先考虑以下一种:

  1. 使用支持异常(或更好的,按照设计契约)的语言编写库,并在合同失败时抛出异常或允许其失败。

  2. 提供错误处理信号/插槽或钩子/回调机制,并调用任何已注册的处理程序。要求在初始化库时至少注册一个错误处理程序。

  3. 支持在每个可能失败的函数中返回某些错误代码,无论出于何种原因。但这是从C(而不是C ++)时代开始的旧方法,相对来说有点疯狂。

  4. 设置一些全局“发生错误”的标志,并允许在调用之前清除该标志。这也是旧的、完全疯狂的方法,主要是因为它将错误状态维护负担转移到了调用者身上,并且在涉及线程时是不安全的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接