4 ms·
My pet peeve with C++ RAII is that it uses destructors for cleanup, so it can’t throw an exception from within the destructor if that fails somehow. E.g. from t
by nathell 1y ago
My pet peeve with C++ RAII is that it uses destructors for cleanup, so it can’t throw an exception from within the destructor if that fails somehow. E.g. from the manual page of close(2):
> A careful programmer will check the return value of close(), since it is quite possible that errors on a previous write(2) operation are reported only on the final close() that releases the open file description. Failing to check the return value when closing a file may lead to silent loss of data. This can especially be observed with NFS and with disk quota.
Last time I checked, GCC’s implementation of ~ofstream() ignored failures from the underlying close().
- flohofwoe 1y agoThis is also a problem when an object referenced by a shared_ptr is destroyed much later than expected because some obscure part of the code still holds a reference to the object. That's why in many situations it makes sense to have an explicitly called discard() method, while the destructor is 'empty' and only checks that discard has actually been called. Of course that also means that RAII isn't all that useful for such situations.
- bluGill 1y agoOne more reason to aviod shared pointers. They are sometimes useful enough as to be worth it, but they make code analisys harder.
- 1718627440 1y agoWhy can't you simply call the destructor, where you would call discard?
- flohofwoe 1y agoBecause there may still be shared pointers in the wild holding a reference to the object and the last of those will call also attempt to call the destructor. With an explicit deinit() method you'd basically get an object that's in an deinitialized, but not destructed state (quite similar to the state a moved-from object is in), the object still exists in memory and can react with proper errors to attempts to access.
- 1718627440 1y agoIs there a way to replace the object with a nullptr instead? Then you can call the destructor any time you like.
- grues-dinner 1y agoThe whole point of a shared_ptr is that you can't delete it out from under other users. You can do exactly what you suggest with a weak_ptr. A shared_ptr to an object with a deinit() is rather like a weak_ptr in that someone else can "delete" it, and you should check if it's really there, except it can still have some information about things like deinit failures rather than just telling you that the object is deleted.
- 1718627440 1y agoIn this case it is clearly intended to be deleted under users, so why not use the language feature for that (destructor) instead of inventing yet another level of book-keeping.
- grues-dinner 1y agoYou can, as long as you don't need to know if/how something within the deinit failed. If you literally just want to know if the item is gone, that's exactly a weak_ptr. File streams, say, do this by expecting users to close() the file themselves if they care if exceptions happen, but if you destruct without doing that first, any exceptions are caught and don't make it out of the destructor, so they're just gone and you'll never know.