问题标签 [raii]

For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.

0 投票
8 回答
12067 浏览

c++ - ScopeGuard 的使用真的会带来更好的代码吗?

我看到了 Andrei Alexandrescu 和 Petru Marginean 多年前写的这篇文章,其中介绍并讨论了一个名为 ScopeGuard 的实用程序类,用于编写异常安全的代码。我想知道使用这些对象进行编码是否真的会导致更好的代码,或者它是否会混淆错误处理,因为也许守卫的回调会更好地呈现在 catch 块中?有没有人有在实际生产代码中使用这些的经验?

0 投票
10 回答
2125 浏览

c# - 是否有比嵌套“使用”更好的确定性处置模式?

在 C# 中,如果我想确定性地清理非托管资源,我可以使用“using”关键字。但是对于多个依赖对象,这最终会越来越嵌套:

在 C++ 中,我习惯于使用析构函数来做到这一点:

在 C# 中有没有更好的方法来做到这一点?还是我坚持多层嵌套?

0 投票
29 回答
121776 浏览

c++ - 在 C++ 中避免内存泄漏的一般准则

有哪些一般提示可以确保我不会在 C++ 程序中泄漏内存?如何确定谁应该释放动态分配的内存?

0 投票
6 回答
48192 浏览

c++ - 为什么将 std::auto_ptr<> 与标准容器一起使用是错误的?

为什么使用std::auto_ptr<>标准容器是错误的?

0 投票
17 回答
131377 浏览

c++ - 如果你不应该在析构函数中抛出异常,你如何处理其中的错误?

大多数人说永远不要从析构函数中抛出异常——这样做会导致未定义的行为。Stroustrup 指出“向量析构函数显式调用每个元素的析构函数。这意味着如果元素析构函数抛出,向量析构失败......确实没有很好的方法来防止析构函数引发的异常,所以库不保证元素析构函数是否抛出”(来自附录 E3.2)

这篇文章似乎另有说法 - 抛出析构函数或多或少是可以的。

所以我的问题是——如果从析构函数中抛出导致未定义的行为,你如何处理析构函数期间发生的错误?

如果在清理操作过程中发生错误,您是否忽略它?如果它是一个可以在堆栈中处理但不能在析构函数中正确处理的错误,那么从析构函数中抛出异常是否有意义?

显然,这类错误很少见,但也有可能。

0 投票
8 回答
8448 浏览

c++ - RAII vs. exceptions

The more we use RAII in C++, the more we find ourselves with destructors that do non-trivial deallocation. Now, deallocation (finalization, however you want to call it) can fail, in which case exceptions are really the only way to let anybody upstairs know of our deallocation problem. But then again, throwing-destructors are a bad idea because of the possibility of exceptions being thrown during stack unwinding. std::uncaught_exception() lets you know when that happens, but not much more, so aside from letting you log a message before termination there's not much you can do, unless you're willing to leave your program in an undefined state, where some stuff is deallocated/finalized and some not.

One approach is to have no-throw destructors. But in many cases that just hides a real error. Our destructor might, for example, be closing some RAII-managed DB connections as a result of some exception being thrown, and those DB connections might fail to close. This doesn't necessarily mean we're ok with the program terminating at this point. On the other hand, logging and tracing these errors isn't really a solution for every case; otherwise we would have had no need for exceptions to begin with. With no-throw destructors we also find ourselves having to create "reset()" functions that are supposed to be called before destruction - but that just defeats the whole purpose of RAII.

Another approach is just to let the program terminate, as it's the most predictable thing you can do.

Some people suggest chaining exceptions, so that more than one error can be handled at a time. But I honestly never actually seen that done in C++ and I've no idea how to implement such a thing.

So it's either RAII or exceptions. Isn't it? I'm leaning toward no-throw destructors; mainly because it keeps things simple(r). But I really hope there's a better solution, because, as I said, the more we use RAII, the more we find ourselves using dtors that do non-trivial things.

Appendix

I'm adding links to interesting on-topic articles and discussions I've found:

0 投票
16 回答
262964 浏览

c++ - C++ 是否支持“最终”块?(我一直听到的这个“RAII”是什么?)

C++ 是否支持“ finally ”块?

什么是RAII 成语

C++ 的 RAII 习语和C# 的“使用”语句有什么区别?

0 投票
17 回答
7312 浏览

c++ - 除了 C++ 之外,其他语言的程序员是否使用、了解或理解 RAII?

我注意到 RAII 在 Stackoverflow 上引起了很多关注,但在我的圈子(主要是 C++)中,RAII 非常明显,就像问什么是类或析构函数一样。

所以我真的很好奇这是因为我每天都被铁杆 C++ 程序员包围,而 RAII 通常并不为人所知(包括 C++),或者是否所有对 Stackoverflow 的质疑都是由于事实我现在接触的程序员不是用 C++ 长大的,而在其他语言中,人们只是不使用/不了解 RAII?

0 投票
7 回答
8685 浏览

.net - 为什么 .NET 中没有 RAII?

作为一名 C++ 开发人员,Java 和 .NET 中缺少RAII(资源获取即初始化)一直困扰着我。清理的责任从类编写者转移到其消费者(通过try finally.NET 的using构造)这一事实似乎明显逊色。

我明白为什么在 Java 中不支持 RAII,因为所有对象都位于堆上,而垃圾收集器本身不支持确定性销毁,但在 .NET 中引入了值类型(struct)我们有(似乎) RAII 的完美候选人。在堆栈上创建的值类型具有明确定义的范围,并且可以使用 C++ 析构函数语义。但是,CLR 不允许值类型具有析构函数。

我的随机搜索发现了一个论点,即如果一个值类型被装箱,它就属于垃圾收集器的管辖范围,因此它的销毁变得不确定。我觉得这个论点不够有力,RAII 的好处大到足以说明带有析构函数的值类型不能被装箱(或用作类成员)。

长话短说,我的问题是:是否有任何其他原因不能使用值类型来将 RAII 引入 .NET?(或者你认为我关于 RAII 明显优势的论点有缺陷吗?)

编辑:我一定没有清楚地表达这个问题,因为前四个答案没有抓住重点。我知道它的非确定性Finalize特征,我知道using构造,我觉得这两个选项不如 RAII。using类的消费者还必须记住一件事(有多少人忘记将 aStreamReader放在一个using块中?)。我的问题是关于语言设计的哲学问题,为什么它是这样的,可以改进吗?

例如,使用通用的确定性可破坏值类型,我可以使usingandlock关键字变得多余(可通过库类实现):


我不禁以我曾经看过但目前无法找到其来源的恰当报价作为结尾。

当我冰冷的死手超出范围时,您可以承担我的确定性破坏。——匿名

0 投票
5 回答
4766 浏览

java - Java中的RAII ...资源处理总是那么难看吗?

我刚刚玩了 Java 文件系统 API,得到了以下函数,用于复制二进制文件。原始来源来自网络,但我添加了 try/catch/finally 子句以确保如果发生错误,缓冲流将在退出函数之前关闭(因此,我的操作系统资源被释放)。

我修剪了函数以显示模式:

据我了解,我不能将两者close()放在 finally 子句中,因为第一个close()可以很好地抛出,然后第二个不会被执行。

我知道 C# 有Dispose模式,可以用using关键字处理这个问题。

我什至更清楚 C++ 代码应该类似于(使用类似 Java 的 API):

我遗漏了一些东西,还是我真的必须在 Java 中生成丑陋和臃肿的代码才能处理close()缓冲流方法中的异常?

(请告诉我我在某个地方错了......)

编辑:是我,还是在更新此页面时,我看到问题和所有答案在几分钟内都减少了一点?是否有人在匿名时太享受自己了?

编辑 2:McDowell提供了一个非常有趣的链接,我觉得我不得不在这里提到:http: //illegalargumentexception.blogspot.com/2008/10/java-how-not-to-make-mess-of-stream.html

编辑 3:在 McDowell 的链接之后,我偶然发现了一个 Java 7 的提案,该提案类似于使用模式的 C#:http: //tech.puredanger.com/java7/#resourceblock。我的问题已明确描述。显然,即使使用 Java 7 do,问题仍然存在。