Jump to content
  • Advertisement
Sign in to follow this  
CoreMeltdown

Multiple serial-dependent allocations

This topic is 4752 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

Hi everyone, please consider this (maybe frequent) C/C++ code:

/* GLOBALS (or class members, or whatsoever...) */

SomeType1 * pT1 = 0;
SomeType2 * pT2 = 0;
/* ... */
SomeTypeN * pTN = 0;

bool MyInitFuncion(void) {
	pT1 = new SomeType1[/* ..size1.. */];
	if (!Check_Or_Use_T1(pT1)) {
		return (false);
	}

	pT2 = new SomeType2[/* ..size2.. */];
	if (!Check_Or_Use_T2(pT2)) {
		delete pT1;
		return (false);
	}

	/* ... */
	/* ... */
	/* ... */

	pTN = new SomeTypeN[/* ..sizeN.. */];
	if (!Check_Or_Use_TN(pTN)) {
		delete pT1;
		delete pT2;
		/* ... */
		/* ... */
		/* ... */
		return (false);
	}

	return (true);
}



As you can see, this code, thus it seems robust (well, at least to me), could be error-prone and quite unpratical. Here is the most-seen solution i've found:

bool MyInitFuncion(void) {
	pT1 = new SomeType1[/* ..size1.. */];
	if (!Check_Or_Use_T1(pT1)) {
		goto my_error;
	}

	pT2 = new SomeType2[/* ..size2.. */];
	if (!Check_Or_Use_T2(pT2)) {
		goto my_error;
	}

	/* ... */
	/* ... */
	/* ... */

	pTN = new SomeTypeN[/* ..sizeN.. */];
	if (!Check_Or_Use_TN(pTN)) {
		goto my_error;
	}

	return (true);

my_error:
	delete pT1;
	delete pT2;
	/* ... */
	/* ... */
	/* ... */
	delete pTN;

	return (false);
}



But "goto"... quite ugly although functional :P Another solution could be to group each runtime allocated pointer (object or array...) into a class/struct and then call a specific free funcion:

void Clean(MyGlobalStruct * pGlobal) {
	delete pGlobal->pT1;
	delete pGlobal->pT2;
	/* ... */
	/* ... */
	/* ... */
	delete pGlobal->pTN;
}

bool MyInitFuncion(void) {
	my_global_struct->pT1 = new SomeType1[/* ..size1.. */];
	if (!Check_Or_Use_T1(my_global_struct->pT1)) {
		Clean(my_global_struct);
		return (false);
	}

	my_global_struct->pT2 = new SomeType2[/* ..size2.. */];
	if (!Check_Or_Use_T2(pT2)) {
		Clean(my_global_struct);
		return (false);
	}

	/* ... */
	/* ... */
	/* ... */

	my_global_struct->pTN = new SomeTypeN[/* ..sizeN.. */];
	if (!Check_Or_Use_TN(my_global_struct->pTN)) {
		Clean(my_global_struct);
		return (false);
	}

	return (true);
}



Consider these examples with explanatory purpose only (substitute operator new with malloc() and delete with free() or every language-specific memory allocation, though the alloc/free code can be seen as generic initialize/finalize code). Some opinions? Thanks :) [Edited by - CoreMeltdown on July 17, 2005 5:51:54 AM]

Share this post


Link to post
Share on other sites
Advertisement
hi desertcube.
thanks for your reply, but IMO it's not focused on my problem, maybe I wasn't clear enough.
The problem is not in pointers' scope.
Say, you have some piece of data you can initialize/finalize.
You initialize a certain datum only if all previous data have been well initialized. If something goes wrong with your last initialization you have to "finalize" all previously-initialized data.

Share this post


Link to post
Share on other sites
No, my post was related. Basically you let a class's constructor/destructor take care of it for you.

For example, say you were dealing with the Win32 API GlobalAlloc, you may want to encapsulate this into a class as follows:

template <class T>
struct GlobalMemory
{
GlobalMemory() {_storage = (T *)GlobalAlloc(GMEM_FIXED, sizeof(T));}
~GlobalMemory() {GlobalFree(_storage);}

T * operator->() {return _storage;}
private:
T * _storage;
};



HTH

Share this post


Link to post
Share on other sites
Probably the nicest version of your code would use smart pointers and look something like this:
bool MyFunction()
{
boost::shared_array<MyType> p1(new MyType[123]);
if(!CheckAndUse(p1)) return false;
boost::shared_array<MyType> p2(new MyType[123]);
if(!CheckAndUse(p2)) return false;
boost::shared_array<MyType> p3(new MyType[123]);
if(!CheckAndUse(p3)) return false;
return true;
}


See: boost::shared_array


Of course, the bunch of if statements looks like it could be worthy of exceptions too, but that will depend on what you're actually doing.

Share this post


Link to post
Share on other sites
Quote:
Original post by CoreMeltdown
thanks for your reply, but IMO it's not focused on my problem, maybe I wasn't clear enough.
The problem is not in pointers' scope.


Actually, if you use std::auto_ptr, it will be.
std::auto_ptr automatically deletes whatever object it points to, when it goes out of scope:

std::auto_ptr<SomeType> ptr1 = 0, ptr2 = 0, ptrn = 0;

bool MyInitFunc()
{
if (!(ptr1 = new SomeType()))
return false;
if (!(ptr2 = new SomeType()))
return false;
if (!(ptr3 = new SomeType()))
return false;
return true;
}




so when you call 'return', anywhere in your function, all of the auto_ptrs will go out of scope, and delete the object they point to.

edit: beaten to it [wink]

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
Quote:
Original post by CoreMeltdown
thanks for your reply, but IMO it's not focused on my problem, maybe I wasn't clear enough.
The problem is not in pointers' scope.


Actually, if you use std::auto_ptr, it will be.
std::auto_ptr automatically deletes whatever object it points to, when it goes out of scope:
*** Source Snippet Removed ***
so when you call 'return', anywhere in your function, all of the auto_ptrs will go out of scope, and delete the object they point to.

edit: beaten to it [wink]


yes you're right... but the auto_ptr you used are declared globals..
Maybe I don't catch you well.... but as far as i know your code snippet cause all allocated pointers to remain allocated once the funcion returns..

Share this post


Link to post
Share on other sites
Quote:
Original post by CoreMeltdown
I am sorry...
consider a C version of my code...


So you want to do it in C, then? No classes, no deconstructors, no RAII, no exception safety, no operator new (then why did you use it)?

In that case, one of your methods in your first post will probably do. I'm sure someone with more plain-C experience can suggest the most elegant method.

Share this post


Link to post
Share on other sites
Quote:
Original post by Andrew Russell
Quote:
Original post by CoreMeltdown
I am sorry...
consider a C version of my code...


So you want to do it in C, then? No classes, no deconstructors, no RAII, no exception safety, no operator new (then why did you use it)?

In that case, one of your methods in your first post will probably do. I'm sure someone with more plain-C experience can suggest the most elegant method.


Well, however, even if i claimed a plain C anwer, the auto_ptr doesn't solve the problem.

Your solution

std::auto_ptr<SomeType> ptr1 = 0, ptr2 = 0, ptrn = 0;

bool MyInitFunc()
{
if (!(ptr1 = new SomeType()))
return false;
if (!(ptr2 = new SomeType()))
return false;
...


if, for example, the second "if" condition is not satisfied, does not deallocate ptr1

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.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!