Jump to content
  • Advertisement
Sign in to follow this  
peter_b

Exceptions and memory management.

This topic is 4640 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hello. Iv recently looked into using exceptions more, the way they are meant to be used. But iv come across something i did not expect to find. It is my belife that exceptions and memory management goes hand in hand. And that exceptions loose their purpose without the other. For instance, it would be impossible to clean up after a function that allocates memory internally and at some point throws an exception. The scope that called the function has no knowleged of what has been allocated. So the only way to avoid memory leaks is to have it deallocated in the pointer to the allocated memory's destroctor. Is this correct? Followup questions to that question is, is there anyway to do memory management in standard c++? I guess i need some smartpointer lib. Is there any such lib that works 100% of the time? I hear you cant make an vector of std::auto_ptr or it will break. True? Second followup: What about memory that is not deallocated by delete, such as dx videomemory, or memory that needs custom deallocation? Any smart ptr that can handle that? Thanks in advance.

Share this post


Link to post
Share on other sites
Advertisement
Quote:
Original post by peter_b
Hello.
Iv recently looked into using exceptions more, the way they are meant to be used.
But iv come across something i did not expect to find.
It is my belife that exceptions and memory management goes hand in hand. And that exceptions loose their purpose without the other.
For instance, it would be impossible to clean up after a function that allocates memory internally and at some point throws an exception. The scope that called the function has no knowleged of what has been allocated. So the only way to avoid memory leaks is to have it deallocated in the pointer to the allocated memory's destroctor.

Is this correct?


Followup questions to that question is, is there anyway to do memory management in standard c++? I guess i need some smartpointer lib. Is there any such lib that works 100% of the time? I hear you cant make an vector of std::auto_ptr or it will break. True?

Second followup: What about memory that is not deallocated by delete, such as dx videomemory, or memory that needs custom deallocation? Any smart ptr that can handle that?


Thanks in advance.


1. Yes, that's pretty much one of the problems.
2. Because of C++'s design, with a smart pointer, because it's a class, it will have it's destructor called when it is no longe needed. If you destruct everything in the smart pointer's deconstructor, you're pretty good off.
3. You're going to have to make it.

Making smart pointers isn't that hard. A few simple overloads and a class template will make it super easy.

Share this post


Link to post
Share on other sites
I remember this being discussed recently in another thread. Someone had a neat thing of declaring a struct local to a function, that had a distructor that cleaned up the pointer when that struct instance went out of scope.

It's like a fudged quicky autopointer.

Share this post


Link to post
Share on other sites
I made a templated smart pointer not to long ago and it wasn't too hard but I did have some trouble. It was reference counted (this data is shared and passed to other pointers internally out of the users sight) so I had trouble getting over the issue of const casts and how I should design my copy constructor. Eventually I resorted to overriding const cast by casting them as non-const in my copy constructor and assignment operator. I know that breaks the concept of a const, but that doesn't work when almost every use of the smart pointer requires access to a shared resource (the reference count).

Anyway, I've heard arguments that C# is better to program in since it manages memory automatically. Personally I agree that C# may have its uses, but the fact that C++ allows you to choose how that memory is managed is still a very worthwile detail. Memory safe C++ can be written and with C++ you have the option of how you make that work. This allows for more creativity (and learning too, if that's why you code) which may lead to new ideas. Hand holding languages like C# take those opportunies away. Although they do have their use that is not my idea of "better."

Share this post


Link to post
Share on other sites
Quote:
Original post by dbzprogrammer
Making smart pointers isn't that hard. A few simple overloads and a class template will make it super easy.
Making them is easy; it's about 20 lines of code.

Getting it right, in the face of multithreading in particular, is extremely hard. Like the rest of the C++ Standard Library, you can build it once to see how it's done, but then use the library version.

The Boost libraries provide several smart pointers (for various situations), among many other incredibly useful things. These smart pointers are part of the C++ standard (in TR1), but GCC 4 is the only compiler that ships them.

To store items in a vector, you need boost::shared_ptr. It also accepts a custom deleter, so it may be possible to use it to free DX surfaces, but it's been so long since I used DX that I've never tried. shared_ptr reference counted, so it can be copied.

boost::scoped_ptr, on the other hand, is designed specifically to handle memory when exceptions are thrown; it can't be copied and clears the memory when it goes out of scope.

Share this post


Link to post
Share on other sites
You can use shared_ptr with COM objects. Ex:

boost::shared_ptr<IDirect3D8> ptr(some_function_that_returns_a_IDirect3D8*(), std::mem_fun(&IDirect3D8::Release));

However, some compilers choke on the mem_fun() call, so you may need to create a thunk to replace it. e.g.:

void releaser(IUnknown * ptr) {
ptr->Release();
}

// ...

boost::shared_ptr<IDirect3D8> ptr(some_function_that_returns_a_IDirect3D8*(), &releaser);

Share this post


Link to post
Share on other sites
One more thing: ATL provides templated "smart" pointers that are designed specifically for COM interfaces - CComPtr<T> and CComQIPtr<T>. The latter supports QueryInterface calls, and both of them correctly handle reference counting (AddRef/Release) for COM objects.

Share this post


Link to post
Share on other sites
Quote:
Getting it right, in the face of multithreading in particular, is extremely hard. Like the rest of the C++ Standard Library, you can build it once to see how it's done, but then use the library version.

I have yet to test my smart pointer in an multithreaded environment, but mines is 127 lines and it uses two variables, the C++ pointer and the reference count object. My reference count object uses a templated handle to access and release the its internal reference count variable (which is an unsinged int). So unless the object being pointed to itself is not thread safe, then this should be a solid method. Only the reference count is modified while being shared across threads, the C++ pointer is only modified once the reference count reaches zero and by then, only one process should have access to the pointer.

Anyway, it urks me when people say that you have to use somebody else's library because it is impossibly hard to make something on your own that works. I have yet to run into something that was "impossibly hard" (script engine without a comiplier/compiler? Doing that right now...). A reference counted smart pointer uses two variables, if you can't make that thread safe then everything else related to multi-threading has to be "impossibly hard" as well.

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Quote:
Original post by peter_b
Second followup: What about memory that is not deallocated by delete, such as dx videomemory, or memory that needs custom deallocation? Any smart ptr that can handle that?


What you need to do is learn about the C++ convention known as "RAII" (resource acquisition is instantiation). The basic idea is to wrap a resource in a class, have it's allocaton contained in the class constructor and the deallocation in the destructor.

Smart pointers are an example of an RAII class.

Google for RAII. The classic books (Stroustrup, Meyers, Sutter) all discuss this technique.

Share this post


Link to post
Share on other sites
Quote:
Original post by T1Oracle
Anyway, it urks me when people say that you have to use somebody else's library because it is impossibly hard to make something on your own that works. I have yet to run into something that was "impossibly hard" (script engine without a comiplier/compiler? Doing that right now...).

Not because it is "impossibly hard", but because re-inventing the wheel is not an efficient use of your time. Of course, if your intention is to learn something from the experience, then that might be good reason to do it yourself.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!