abseil / abseil/abseil-cpp

Throwing callback leads to program terminations in absl::Cleanup

未关闭
#1,238 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
bug
主要语言
C++
星标
18.1k
派生
3.2k
平均合并
20 小时 36 分钟
30 天内合并 PR
1

描述

**Describe the bug**
Let `Callback` be a type, whose `operator()` is `noexcept(false)` and actually throws.
When an object of such a type is passed as the callback for `absl::Cleanup`, then the destructor `~Cleanup` will always abort the program at runtime, because it is (implicitly) `noexcept`.

I would expect one of the following two possibilities:
- The program doesn't compile, because `Cleanup` `static_assert`s that the callback type is `nothrow_invocable`.
- The destructor propagates the exception (this would require marking it `noexcept(std::is_nothrow_invocable_v)`.

**Steps to reproduce the bug**
Consider the following minimal example:
```
#include
int main() {
try {
absl::Cleanup cl{[]() {throw 42;}};
} catch(...) {}
}
```
[Link to godbolt](https://godbolt.org/z/9cz1K4fTf)

**What system are you using**
I am using Ubuntu 22.04 and G++ 11.1, but the behavior should be the same on
any standard-conforming compiler and platform.

**Additional context**
I am aware that "throwing destructors" are a somewhat controversial topic. Maybe a compromise would be, to `static_assert` as a default, but to provide a possibility to opt out of that assertion, e.g.:

```
absl::Cleanup cl{[]() noexcept {}}; // Fine
absl::Cleanup cl2{[]() {throw 42;}}; // Assertion failure, not noexcept
absl::Cleanup cl3{[]() {throw 42;}}; // Fine
```

I am willing to provide an implementation as soon as we have discussed, what the desired behavior should be.

A problem might be, that the "safer" suggestions (involving the `static_assert`) are a breaking change for callback types that do not throw, but are not explicitly marked `noexcept`.

Best regards
Johannes

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。