By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
449,110 Members | 990 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 449,110 IT Pros & Developers. It's quick & easy.

try-catch blocks & memory leaks

P: n/a
Below are three try-catch blocks. My question is, how can all three work,
and how come there is no memory leak (or is there)? As I understand it, an
exception object is being created and "thrown" back to the calling function.
If you treat this object as a reference or copy it, how does it get cleaned
up?

/* code segment 1 */
try {
m_pCommand->Execute(NULL, NULL, adCmdText | adExecuteNoRecords);
}
catch(_com_error *e) { // pointer
DumpComError(e);
delete e;
return NULL;
}

/* code segment 2 */
try {
m_pCommand->Execute(NULL, NULL, adCmdText | adExecuteNoRecords);
}
catch(_com_error &e) { // reference
DumpComError(e);
// can't delete e
return NULL;
}

/* code segment 3 */
try {
m_pCommand->Execute(NULL, NULL, adCmdText | adExecuteNoRecords);
}
catch(_com_error e) { // copy of original error
DumpComError(e);
// can't delete e
return NULL;
}

/* done */

TIA,
C. Martin

Jul 22 '05 #1
Share this Question
Share on Google+
4 Replies


P: n/a
* "Chris Martin" <no****@please11111.net> schriebt:
Below are three try-catch blocks. My question is, how can all three work,
The blocks you show seems to have different assumptions about what 'Execute'
throws.
and how come there is no memory leak (or is there)?
Your first example has a possible memory leak.
As I understand it, an
exception object is being created and "thrown" back to the calling function.
If you treat this object as a reference or copy it, how does it get cleaned
up?
Each copy of the object is cleaned up via a call to its destructor.

/* code segment 1 */
try {
m_pCommand->Execute(NULL, NULL, adCmdText | adExecuteNoRecords);
}
catch(_com_error *e) { // pointer
This catches a 'com_error*'. It does not catch a 'com_error'.
DumpComError(e);
Here is a possible memory leak: if 'DumpComError' throws then 'delete'
will not be called.
delete e;
return NULL;
}

/* code segment 2 */
try {
m_pCommand->Execute(NULL, NULL, adCmdText | adExecuteNoRecords);
}
catch(_com_error &e) { // reference
This catches a 'com_error'. It does not catch a 'com_error*'. By the way,
as a matter of good coding style you should never catch by reference to
non-const, as is done here, but only by reference to const.
DumpComError(e);
// can't delete e
return NULL;
}

/* code segment 3 */
try {
m_pCommand->Execute(NULL, NULL, adCmdText | adExecuteNoRecords);
}
catch(_com_error e) { // copy of original error
This catches a 'com_error'. It does not catch a 'com_error*'. To avoid
excessive copying overhead catch by reference to const instead.

DumpComError(e);
// can't delete e
return NULL;
}


Jul 22 '05 #2

P: n/a
The blocks you show seems to have different assumptions about what 'Execute' throws.
I can't seem to find any documentation on -what- Execute throws. I believe
all three catches worked correctly though.
Each copy of the object is cleaned up via a call to its destructor.


When is the destructor called? For a reference I can't delete it in order
for the destructor to be called. Wouldn't it have to be on the heap? Same
with the copied object.
/* code segment 1 */
try {
m_pCommand->Execute(NULL, NULL, adCmdText | adExecuteNoRecords);
}
catch(_com_error *e) { // pointer


This catches a 'com_error*'. It does not catch a 'com_error'.


I don't understand your point.
DumpComError(e);


Here is a possible memory leak: if 'DumpComError' throws then 'delete'
will not be called.


But if it doesn't, when will delete be called?

I obvoiusly have a flawed understanding of how exception handling really
works.

Thanks for the reply,
C. Martin
Jul 22 '05 #3

P: n/a
Chris Martin wrote:
The blocks you show seems to have different assumptions about what
'Execute' throws.
I can't seem to find any documentation on -what- Execute throws.


Then it's a case of extremely bad documentation.
I believe all three catches worked correctly though.
That's very unlikely. The function cannot throw two types at the same
time, and a _com_error and a pointer to it are two separate and
unrelated types.
Each copy of the object is cleaned up via a call to its destructor.


When is the destructor called? For a reference I can't delete it in
order
for the destructor to be called. Wouldn't it have to be on the heap?
Same with the copied object.
> /* code segment 1 */
> try {
> m_pCommand->Execute(NULL, NULL, adCmdText | adExecuteNoRecords);
> }
> catch(_com_error *e) { // pointer


This catches a 'com_error*'. It does not catch a 'com_error'.


I don't understand your point.


_com_error* and _com_error are different types. The above will only
catch if a pointer to _com_error was thrown, not if a _com_eror was
thrown directly.
> DumpComError(e);


Here is a possible memory leak: if 'DumpComError' throws then
'delete' will not be called.


But if it doesn't, when will delete be called?


What do you mean? If DumpComError doesn't throw, then delete will be
called afterwards. That's what you wrote in your code.
I obvoiusly have a flawed understanding of how exception handling
really works.


Maybe. But I have no idea what your exact understanding of it is.

Jul 22 '05 #4

P: n/a
"Chris Martin" <no****@please11111.net> wrote in message news:<pPA%b.69050$4o.90319@attbi_s52>...
The blocks you show seems to have different assumptions about what 'Execute'
throws.


I can't seem to find any documentation on -what- Execute throws. I believe
all three catches worked correctly though.


That depends on your definition of "correctly".
Each copy of the object is cleaned up via a call to its destructor.
When is the destructor called? For a reference I can't delete it in order
for the destructor to be called. Wouldn't it have to be on the heap? Same
with the copied object.


This is done by the errorhandling mechanism: it is responsible for
cleaning up your exception-objects.
/* code segment 1 */
try {
m_pCommand->Execute(NULL, NULL, adCmdText | adExecuteNoRecords);
}
catch(_com_error *e) { // pointer


This catches a 'com_error*'. It does not catch a 'com_error'.


I don't understand your point.

[snip]

try running this snippet (not tested)

try
{
int throwval(0);
throw throwval; // throw an integer
}
catch (int i)
{
std::cout << "caught int: " << i << '\n';
}
catch (int *pi)
{
std::cout << "caught pointer to int: " << pi << '\n';
}
catch (...)
{
std::cout << "caught something else" << '\n';
}
try
{
int* throwval(0);
throw throwval; // throw a pointer to an integer
}
catch (int i)
{
std::cout << "caught int: " << i << '\n';
}
catch (int *pi)
{
std::cout << "caught pointer to int: " << pi << '\n';
}
catch (...)
{
std::cout << "caught something else" << '\n';
}
Jul 22 '05 #5

This discussion thread is closed

Replies have been disabled for this discussion.