• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
arka80

Destructors or Release methods?

17 posts in this topic

Every time I design something I fall into this dilemma: should I clear things on destructors or should I make a (public) Release method? And if I make the Release method, should I automatically call it on destructor (again! ohmy.png ) or should I leave the programmer (well... me tongue.png ) free to call it whenever he wants?

 

Pros and cons that I can miss?

Edited by arka80
0

Share this post


Link to post
Share on other sites

Can you be a little more technical about what you mean by "clear things?" In general, each object should cleanup after itself. If it creates or allocates, it's responsible for releasing or deallocating its own resources. Some objects may need to create/release several times throughout its lifetime, as needed. Leaving those decisions to another object doesn't make sense.

 

Having a public Release method and also calling it in the destructor sounds like a recipe for disaster.

Edited by Buckeye
1

Share this post


Link to post
Share on other sites

I'm also of the idea that an object should clear itself in a transparent way, but in a lot of well known API objects has some kind of public Release method. Why?

 

EDIT: with "clear things" I mean the usual call of delete commands and pointers nullify

Edited by arka80
0

Share this post


Link to post
Share on other sites

If it makes sense to release resources before the objects gets destructed (and its memory freed) then make a public method. If it doesnt then clean it up in the destructor and dont add an unnecessary protected: release() method.

 

pointer nullify? ....you mean after you delete something you set the pointer to nullptr so if someone calls delete again, it wont crash? Sounds bad. RAII would be more sane. And if you use raw pointers or arrays, make a has_memory_allocated or something member so you know that it can be freed(maybe the allocation has failed in the constructor).

0

Share this post


Link to post
Share on other sites

a lot of well known API objects has some kind of public Release method. Why?

Because you don't delete those types of objects. You create them; you release them. Note: if you're talking about COM objects, you can also AddRef/Release in matched pairs.

 

To clarify, I'm assuming you're talking about an object that, when it's created or allocated, then creates and allocates for itself needed objects. E.g.,

Object::Object()
{
    Create( device ); // EDIT: or device->AddRef()
    GlobalAlloc( myMemory );
}

Object::~Object()
{
    if( device ) Release( device ); // Note: the object's responsibility.
    //device = NULL; // NO!!
    if( myMemory ) GlobalFree( myMemory ); // because this object allocated it.
    myMemory = NULL; // Not really necessary?
}

For COM objects, Release() must be public. How would you release it otherwise? smile.png

 

Releasing the device (in the above) may not result in the device's destruction, if other objects needed it, called device->AddRef, and haven't called Release yet. That's not this Object's responsibility. The device will take care of itself.

Edited by Buckeye
1

Share this post


Link to post
Share on other sites

Well, if I understand correctly - you might want to "release" your memory from time to during the object's lifetime. If you were writing something like a smart pointer, then, sure, a release method that you call is a very sane thing to do, unless you want to duplicate code. Other than a smart pointer, I don't remember if I had to have a clean-up method besides the destructor.

Edited by dilyan_rusev
0

Share this post


Link to post
Share on other sites


If you were writing something like a smart pointer, ...

I'm not as knowledgeable of smart pointers as I ought to be. However, do you mean shared pointer, perhaps? I was considering heap allocations needed only (exclusive ownership) by the object.

0

Share this post


Link to post
Share on other sites

You can have both, like std::fstream. There there exists a close method, which is called by the destructor if the file is not already closed. You can make it so that calling the clean-up method more than once is safe to do. More often, just releasing and cleaning up in the destructor is the best option. And because you do want to leave the system in a safe state, having clean-up as a method, but not as a destructor is usually bad. 

2

Share this post


Link to post
Share on other sites

The only times I've seen Release() methods are when there are matching AddRef() or similar, that is reference counted objects.

 

Edit: There are some more legitimate uses. For example a scripting language may require explicit release methods in order to function correctly/automatically. There are also some reasons to work with interfaces, such as when creating libraries, where it may be cleaner or more desirable to use explicit releasing. In such cases, it's not too uncommon to create RAII wrappers around those interfaces.

Edited by DvDmanDT
1

Share this post


Link to post
Share on other sites

I think the only time you should need a separate Release method (instead of just a destructor) is if:

- you are implementing your own reference counting (e.g. like a COM object does, paired with AddRef), or

- your object holds onto system resources and you want your object to be able release those important system resources before it goes out of scope or is destroyed (such as a File object releasing a file handle, a texture object releasing the underlying GPU resource, something like that).

Edited by phil_t
0

Share this post


Link to post
Share on other sites

Personally I use CComPtr for (d3d) objects and only set them to null in the destructor, no releasing/ release calls needed.

A stripped example:

#include <atlbase.h>

class CD3d
{
public:
	CComPtr<IDirect3DDevice9>	mD3ddev;		// smart pointer, first LPDIRECT3DDEVICE9

// etc

CD3d::CD3d()
{
	mD3ddev					= NULL;		// smart pointer
// etc

CD3d::~CD3d()
{
	// Smart pointers
	mD3ddev		= NULL;
// etc

This way I never have memory leaks.

Not 100% sure though if it's really necessary to set them to NULL / nullptr. If not, you could save yourself making your own constructor/destructor (rule of 3?) and let the compiler do it automatically for you.

Edited by cozzie
0

Share this post


Link to post
Share on other sites

The problem as I see it is by having a Release() method, you are then implying that instances of your class can exist in two states - formed and released. After you call Release(), your object is still around and can still be operated upon, so your internals of the class and your users then need to code around this, checking the state of the object during any operations.

 

One of the strongest principles of encapsulation is class invariants - if I have a std::string object, I am guaranteed from the outside to have an object containing a valid string or the empty string. I don't have to check isValid() every time.

 

In an ideal world (in which I accept we are not) it is better to use object lifetime to model the lifetime of the resource being modelled, then your objects can and need only exist in a formed state.

1

Share this post


Link to post
Share on other sites

Thank you guys, I have a clear vision now, and think I'll get rid of Release methods for a while, since I use raw pointers and no ref counts. Long life to destructors.

0

Share this post


Link to post
Share on other sites

frob - Yes, I understand that you weren't suggesting uninitialized objects. What I am saying is that you can model what you are talking about using composition and object lifetime, then you don't need to worry about the "empty" state if the empty state only needs to exist in order to accommodate delayed loading for example.

 

If the empty state is not a conceptual feature of the object, but an implementation detail to allow for delayed loading, this can be expressed via having the object contained in a proxy then the acquisition (delayed) and freeing of the actual object can be modelled using the object lifetime, just as a member of a proxy object.

 

The proxy can then handle releasing its owned resource, possibly in a generic way and the actual resource itself need only maintain as invariant its populated state. Then when you have acquired the resource from the proxy, you always have a guaranteed formed object to work with and the proxy takes care of ensuring it is populated, perhaps in a just-in-time manner.

 

But this is design nitpicking and probably not very related to the real world. In reality of course a Mesh object will have a vertexCount == 0 state and if this mechanism is used to implement a decision at each use as to whether to load it or not before use, its much the same thing I suppose, except this is unwrapped so has to be performed all over the place.

Edited by Aardvajk
1

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0