I was able to listen to Dr. C Parent Bjarne Stroustrup's lectures on the Tsinghua University's Architecture Branch on October 26th. Wonderful speeches, fascinating content, is unforgettable. At the same time, I also felt that the master of the master in the next listening to the listener's question and tested. The theme of this lecture is Exception Safety, the following is after I have finished the lecture, combined with my own body, think about the C Exception Handling and related content, if there is consideration, please refer to it.
In C language, resource management (Managing Resources) is always a very important topic, and the programmer needs to pay very attention when using the C language to write code, it is a little inappreciable to lead to resource leaks, in my previous programming Such problems are often encountered in practice. "Resource Acquisition In InIction" is a better way to handle such issues, this is what Stroustrup is mentioned in the speech. This is also mentioned in the D & E of Dr. and related papers. This method uses a class to represent the management logic of the resource, pass the handle (pointer or reference) to the resource via the CTOR, which is responsible for release the resource by the Dtor when the instance of the class is destroyed. You can apply for resources before creating such an instance, or you can apply for resources by the CTOR of this class during construction. The basic idea of this way is whether the Exception happens, since the C language mechanism guarantees, it will call the DTOR of the current scope object, so as long as the resource recycled code is added, then these code will always be implemented. The advantage of this method is that since the logic recycling logic is peeled off from the original code through a separate class, the programmer will always do not miss it, and the idea has become clear.
I think the "Resource Acquisition in Initialization" technique, the application range can also be extended when handling questions about Exception. Not only to resource management, as long as there is a symmetrical operation like FOPEN / FCLOSE, New / Delete, it is possible to consider using this method as appropriate. Avoiding resource leaks is a big event, which should be listed within Basic Guarantee. But some symmetry operations, if it affects the normal execution of the program, it is not despised even if it produces Fatal Error. For a software, put an endal error should be an Basic Guarantee.
The following is an example I have encountered in practice. Interestingly, this example is the first time I decided to use Exception Handling for the first time in the Software module, which can be unfavorable :) After the simplified code is basically the following: Void f (c * pobj) {Pobj-> Editable (TRUE); // do some work with object pobj-> editable (false);} The role of the function f is some of the objects referred to in POBJ that passes to its scope. When the Exception Handling is originally introduced, the code changes as follows: Void f (c * pobj) {pobj-> editable (true); try {// do some work with object // may cause exception} catch (...) {/ / do some think and restiw;} POBJ-> Editable (false);} This Rethrow is to make F's calorificers can have some processing, which is required when designing. A practice like this is very common in a general Exception handler, but my negligence has eaten a big loss. Although it is easy to see the flaw from the simplified code, due to the lack of experience, the procedure logic is complex until the final GUI is discovered by the final GUI. After a few hours of hard debugging, the final found in the F function. In fact, the behavior of the function f implies an assert, ie, is not to make changes to the in-picture of the object referred to in Pobj, and the object call F pre-F pre-forth is not editable, and then there is still the case after the call. In the above program, when the Exception occurs, since the statement does not perform POBJ-> Editable (False), the program is final error, and this error is hidden in countless code, the Exception situation is not every time, Make me a lot of energy when I am debugging. After finding the wrong roast, I adopted the following remedies, this practice was called by Dr. Stroustrup called Naive Use: Void F (C * Pobj) {Pobj-> Editable (TRUE); try {// do some work with Object // may cause exception} catch (...) {// do somehing and reason pobj-> editable (false); throw;} Pobj-> Editable (false);} When writing this code, Intuition tells yourself, there is Bed Smell here, but because of time is urgent, this time, it is temporarily tolerated. The practice of Quick and Dirty. As Stroustrup Dr. Strous is pointed out in D & E, the disadvantage of this approach is that it is long, and it is expensive. Take a closer analysis, you can see the potential dangers here: two POBJ-> Editable (false) is in fact duplicate code, we need to always maintain the consistency of both code, if a period of time, you need to increase in POBJ A similar to Editable properties, this consistency is maintained, it is difficult to ensure that it will not be neglected again.
So, in accordance with the master's teachings, I added a secondary class: class c_handle {c * _pobj; public: c_handle (c * pobj) {_pobj = pobj; _pobj-> Editable (TRUE); // May Be Other Operations} ~ c_handle () {_pobj-> editable (false); // also may be operator c * () {return_pobj;}}; c_handle's CTOR and DTOR, pair _Pobj The operation is pairing, so it is not easy to make mistakes when expanding later. At this time, the code of the F function has also become simpler: Void F (c * pobj) {c_handle ch (pobj); try {// do some work with object // may cause exception} catch (...) {/ / do some think and rebthrow throw;}} Individual feels that this technique should have universal significance. Since now: Several symmetry operations for an object appears in a scope, and Exception may throw an Exception between the two sets of operations that are symmetrical with each other, and this destruction will result in the SCOPE-related When a certain Assert is False, you can consider this "Resource Acquisition in Initialization" technique recommended by Dr. Stroustrup in handling resource management issues. It can even be considered that the examples of resource management have occurred here. Another typical example in resource management is Smart Pointer.
In addition, one disadvantage that this method may exist is that many auxiliary classes like C_Handle are similar. We can think about this: If these categories are not a lot, then their existence will benefit from the preparation and maintenance of the code (think about the price of the maintenance consistency mentioned earlier), and if there is a number of programs These classes can be multiplexed when they are similar. When the number of classes makes you unable to tolerate, you should consider the necessity of some of the existence of some classes. After all, it is not a procedure to use Exception Handling, maybe your design itself has problems. In addition, if these assisted classes are associated with each other, consider introducing inheritance systems, and if their behavior and similarity, use the Template mechanism for generalization, and it is not a optimization strategy.