我的库应该在错误的指针输入上处理 SIGSEGV 吗?

发布于 2024-12-28 21:43:38 字数 383 浏览 1 评论 0原文

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

如果我立即检查这个 FILE * 指针并发现它导致了段错误,那么处理该信号、设置 errno 并优雅退出是否更正确?或者什么都不做并使用调用者安装的信号处理程序(如果有的话)?

普遍的观点似乎是“图书馆永远不应该导致崩溃”。但我的想法是,既然这个特定的信号肯定是呼叫者的错,那么我不应该试图向他隐藏该信息。他可能安装了自己的处理程序,以自己的方式对问题做出反应。可以使用 errno 检索相同的信息,但是设置 SIGSEGV 的默认配置是有充分理由的,并且向上传递信号通过强制调用者处理他的错误,或者通过崩溃并保护他免受进一步的损害来尊重这一理念。 。

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

I'm writing a small library that takes a FILE * pointer as input.

If I immediately check this FILE * pointer and find it leads to a segfault, is it more correct to handle the signal, set errno, and exit gracefully; or to do nothing and use the caller's installed signal handler, if he has one?

The prevailing wisdom seems to be "libraries should never cause a crash." But my thinking is that, since this particular signal is certainly the caller's fault, then I shouldn't attempt to hide that information from him. He may have his own handler installed to react to the problem in his own way. The same information CAN be retrieved with errno, but the default disposition for SIGSEGV was set for a good reason, and passing the signal up respects this philosophy by either forcing the caller to be handle his errors, or by crashing and protecting him from further damage.

Would you agree with this analysis, or do you see some compelling reason to handle SIGSEGV in this situation?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

夜空下最亮的亮点 2025-01-04 21:43:38

接管处理程序不是图书馆的事,我想说,除非明确要求,否则这有点冒犯他们。为了最大限度地减少崩溃,库可能会在某种程度上验证其输入。除此之外:垃圾进——垃圾出。

Taking over handlers is not library business, I'd say it's somewhat offensive of them unless explicitly asked for. To minimize crashes library may validate their input to some certain extent. Beyond that: garbage in — garbage out.

以为你会在 2025-01-04 21:43:38

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

我不知道你从哪里得到的——如果它们传递了一个无效的指针,你应该崩溃。任何图书馆都会。

The prevailing wisdom seems to be "libraries should never cause a crash."

I don't know where you got that from - if they pass an invalid pointer, you should crash. Any library will.

不羁少年 2025-01-04 21:43:38

我认为检查 NULL 指针的特殊情况是合理的。但除此之外,如果他们传递垃圾,他们就违反了函数的合同,并且会崩溃。

I would consider it reasonable to check for the special case of a NULL pointer. But beyond that, if they pass junk, they violated the function's contract and they get a crash.

凯凯我们等你回来 2025-01-04 21:43:38

这是一个主观问题,可能不适合 SO,但我将提出我的意见:

这样思考:如果您有一个函数采用 nul 终止的 char * 字符串并记录在案因此,并且调用者传递了一个没有 nul 终止符的字符串,您是否应该捕获信号并拍打调用者的手腕?或者你应该让它崩溃并让糟糕的程序员使用你的 API 修复他/她的代码?

如果您的代码采用 FILE * 指针,并且您的文档显示“传递任何打开的 FILE *”,并且它们传递关闭或无效的 FILE * > 反对,他们违反了合同。检查这种情况会减慢那些正确使用你的库的人的代码,以适应那些不正确使用你的库的人,而让它崩溃将使那些阅读文档并编写良好代码的人尽可能快地保持代码。

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

This is a subjective question, and possibly not fit for SO, but I will present my opinion:

Think about it this way: If you have a function that takes a nul-terminated char * string and is documented as such, and the caller passes a string without the nul terminator, should you catch the signal and slap the caller on the wrist? Or should you let it crash and make the bad programmer using your API fix his/her code?

If your code takes a FILE * pointer, and your documentation says "pass any open FILE *", and they pass a closed or invalidated FILE * object, they've broken the contract. Checking for this case would slow down the code of people who properly use your library to accommodate people who don't, whereas letting it crash will keep the code as fast as possible for the people who read the documentation and write good code.

Do you expect someone who passes an invalid FILE * pointer to check for and correctly handle an error? Or are they more likely to blindly carry on, causing another crash later, in which case handling this crash may just disguise the error?

鸠魁 2025-01-04 21:43:38

如果您向内核提供错误的指针,内核不应该崩溃,但库可能应该崩溃。这并不意味着您不应该进行错误检查;一个好的程序在面对不合理的坏数据时会立即死亡。我宁愿用assert(f != NULL) 调用库来保释,而不是仅仅继续并最终取消引用NULL 指针。

Kernels shouldn't crash if you feed them a bad pointer, but libraries probably should. That doesn't mean you should do no error checking; a good program dies immediately in the face of unreasonably bad data. I'd much rather a library call bail with assert(f != NULL) than to just trundle on and eventually dereference the NULL pointer.

与往事干杯 2025-01-04 21:43:38

抱歉,但是那些说库应该崩溃的人只是懒惰(也许是考虑时间以及开发工作)。库是函数的集合。库代码不应该“直接崩溃”,就像软件中的其他功能不应该“直接崩溃”一样。

诚然,如果通常涉及多种语言或(相对)外来语言功能(例如异常),库可能会在如何跨 API 边界传递错误方面遇到一些问题,但没有什么特别之处。实际上,这只是编写库的负担的一部分,而不是应用程序内的代码。

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

有多种方法可以处理此问题,按照优先顺序,您可能应该执行以下操作之一:

  1. 使用支持库内异常(或更好,按合同设计)的语言,并在或允许合约失败。

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

  3. 支持在每个可能因任何原因失败的函数中返回一些错误代码。但这是从 C(而不是 C++)时代开始的一种古老的、相对疯狂的做事方式。

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

Sorry, but people who say a library should crash are just being lazy (perhaps in consideration time, as well as development efforts). Libraries are collections of functions. Library code should not "just crash" any more than other functions in your software should "just crash".

Granted, libraries may have some issues around how to pass errors across the API boundary, if multiple languages or (relatively) exotic language features like exceptions would normally be involved, but there's nothing TOO special about that. Really, it's just part of the burden of writing libraries, as opposed to in-application code.

Except where you really can't justify the overhead, every interface between systems should implement sanity checking, or better, design by contract, to prevent security issues, as well as bugs.

There are a number of ways to handle this, What you should probably do, in order of preference, is one of:

  1. Use a language that supports exceptions (or better, design by contract) within libraries, and throw an exception on or allow the contract to fail.

  2. Provide an error handling signal/slot or hook/callback mechanism, and call any registered handlers. Require that, when your library is initialised, at least one error handler is registered.

  3. Support returning some error code in every function that could possibly fail, for any reason. But this is the old, relatively insane way of doing things from C (as opposed to C++) days.

  4. Set some global "an error has occurred flag", and allow clearing that flag before calls. This is also old, and completely insane, mostly because it moves error status maintence burden to the caller, AND is unsafe when it comes to threading.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文