471,585 Members | 1,165 Online
Bytes | Software Development & Data Engineering Community
Post +

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 471,585 software developers and data experts.

try-catch blocks & memory leaks

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
4 9388
* "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
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
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
"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.

Similar topics

39 posts views Thread by Erlend Fuglum | last post: by
4 posts views Thread by Brian Alexander | last post: by
13 posts views Thread by KefX | last post: by
9 posts views Thread by David Stockwell | last post: by
6 posts views Thread by William Park | last post: by
4 posts views Thread by wk6pack | last post: by
3 posts views Thread by Sori Schwimmer | last post: by
2 posts views Thread by Shi Mu | last post: by
reply views Thread by XIAOLAOHU | last post: by
reply views Thread by leo001 | last post: by
reply views Thread by Anwar ali | last post: by

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.