• Advertisement
Sign in to follow this  

Dynamic Memory and throwing Exceptions

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

I'm looking for some guidance when it comes to allocating dynamic memory and throwing exceptions.
 
So lets say I have a situation where I need to create some dynamic memory based on a value returned by a function
 
int size = GetSomeSize();
int *buffer = new int[size];
 
Now lets say I need to use this buffer variable later on in the program.
Where I pass it to a function that has the ability to purposely throw a run time error. In addition this function does not attempt to catch the runtime error.
 
So we are looking at something like:
 
int size = GetSomeSize();
int *buffer = new int[size];
BufferManip(buffer);
 
What happens if:
 
1. The function (BufferManip) fails? What happens to the dynamic memory if an outside function catches the runtime error thrown?
2. What happens if the function catches the runtime error? What happens to the dynamic memory allocated?
3. What is the best way to handle situation where you need dynamic memory and you know an exception can be thrown? Edited by noodleBowl

Share this post


Link to post
Share on other sites
Advertisement

1. The function fails? What happens to the dynamic memory if an outside function catches the runtime error thrown?

Assuming you mean BufferManip throws an exception, the answer is it depends on the calling code.
 
Let's say you have this code
 
int size = GetSomeSize();
int *buffer = new int[size];
BufferManip(buffer);
delete buffer;
if BufferManip throws an exception then delete buffer won't be called and you have a memory leak. 
 
you could fix this by catching the exception.
int size = GetSomeSize();
int *buffer = new int[size];
try
{
  BufferManip(buffer);
}
catch (...)
{
   delete buffer;
}

2. What happens if the function catches the runtime error? What happens to the dynamic memory allocated?

If BufferManip swallows the exception (i.e. it doesn't propagate up the stack), then buffer can be deleted.

3. What is the best way to handle situation where you need dynamic memory and you know an exception can be thrown?

Don't use a raw pointer. Use a vector.

Bear in mind that the new operator can throw an exception if it can't allocate the requested memory.

Also, most games don't use exceptions. Edited by ChaosEngine

Share this post


Link to post
Share on other sites


you could fix this by catching the exception.

int size = GetSomeSize();
int *buffer = new int[size];
try
{
BufferManip(buffer);
}
catch (...)
{
delete buffer;
}

...and now the delete is not called in the common case when no exception is thrown. If there was an exception its silently discarded.

Because its so easy to make a mistake with this you should really avoid using new and delete manually. You could use a vector or unique_ptr instead to have this problem handled automatically.

Edited by wintertime

Share this post


Link to post
Share on other sites

Also, most games don't use exceptions.


Then what do games do? Are you implying that games just crash?
Or are you saying they don't purposely toss errors?
 

Because its so easy to make a mistake with this you should really avoid using new and delete manually. You could use a vector or unique_ptr instead to have this problem handled automatically.


Is a unique_ptr the same as a smart pointer?

I guess more specifically I'm talking something like this:
int main()
{
	try
	{
		MyObject a;
		ManipObject(a);
	
	}
	catch (std::runtime_error &e)
	{
		std::cout << e.what() << std::endl;
	}

}

void ManipObject(MyObject &a)
{
	int size = GetSomeSize();
	int *buffer = new int[size];
	
	//Can throw exception
	BufferManip(a, buffer);
	
	delete [] buffer;
}

void BufferManip(MyObject &a, int *buffer)
{
	//Just some example codes
	if(a.var == 0)
		buffer[0] = 1;
	else if(a.var == 1)
		buffer[0] = 2;
	else
		throw std::runtime_error("Invalid MyObject val!");		
}

In this case buffer never gets cleaned up if an exception is thrown. But since the program then would end do I really have a mem leak?
If I never have the try catch, the program would then just crash so is it better not to handle it?

What about only handling it for logging purposes? I basically just want the try catch there because it will let me know where my program
failed when I run it outside the compiler

Since we are on the top of dynamic memory
What happens if I do something like this?


int *buffer = new int[1024];
BufferManip(a, buffer);

buffer = new int[2048];
BufferManip(a, buffer);
delete [] buffer;

Should I be deleting before I do the second new? Or does it not matter? Edited by noodleBowl

Share this post


Link to post
Share on other sites


Is a unique_ptr the same as a smart pointer?

A unique_ptr is more like the old auto_ptr. It specifies exactly one owner, whereas smart_ptr specifies an unknown number of owners.

 

That makes unique_ptr extremely lightweight, and is explicitly designed to solve this issue. You should, 99% of the time, be using std::vector to manage memory buffers, with std::unique_ptr to fill the remaining cases.

Share this post


Link to post
Share on other sites

...and now the delete is not called in the common case when no exception is thrown. If there was an exception its silently discarded.
Because its so easy to make a mistake with this you should really avoid using new and delete manually. You could use a vector or unique_ptr instead to have this problem handled automatically.


HA! The funny thing is, the whole point of my post was to point out that you shouldn't use raw pointers without a very good reason. I wrote that code without thinking and I screwed it up... and people wonder why best practice is to use vectors biggrin.png
 

Then what do games do? Are you implying that games just crash?
Or are you saying they don't purposely toss errors?


I saying that many games will disable exceptions in their C++ compiler, and use some other error handling mechanism.

Historically exception support in console C++ compilers has been pretty bad. Not sure if that's improved with the current generation.

What happens if I do something like this?

int *buffer = new int[1024];
BufferManip(a, buffer);

buffer = new int[2048];
BufferManip(a, buffer);
delete [] buffer;
 Should I be deleting before I do the second new? Or does it not matter?

 

You shouldn't do that. You are allocation 4k bytes somewhere in memory. Then you throw away the address of those 4k bytes, so you can't tell the OS you're finished with that memory.
 
What does that mean in practice? For this example, on a modern OS, on a machine from this century? Almost nothing. You lose 4k of memory and then the OS will clean it up when you exit the program.
 
But it's a bad habit to get into. If that was a bigger chunk of memory, or that was in some code called in a loop, it could become a problem.

 

 

Seriously, just use a vector. It will make your life so much easier. 

Share this post


Link to post
Share on other sites

whereas smart_ptr specifies an unknown number of owners.

 

What's smart_ptr? Do you mean shared_ptr?

 

 

To the O.P.: As others have said, use vector. Possibly unique_ptr<int[]> is another option, if the semantics of unique_ptr fit your usage scenario.

 

Also, this is essential reading if you are allocating memory or acquiring any unmanaged resources (file handles, critical sections, etc...) in an environment where exceptions can be thrown:

http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization

Edited by phil_t

Share this post


Link to post
Share on other sites

Maybe worth recalling somebody isn't AAA. Exceptions are extremely handy and considering the first few posts of this thread are clearly written by someone who doesn't have an accurate view of what's going on, I'd suggest to stick to what C++ suggests to do as canon as long as there isn't a specific product to talk about.

Share this post


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

  • Advertisement