Hello,
This question was asked in comp.lang.c++ and the answers involved the use of
objects whose destructors are automatically called when getting out of
scope, however I was expecting suggestions that doesn't involve the use of
objects. So here is the question again.
I have a function like:
void fnc() {
char *mem1, *mem2, *mem3, *mem4;
FILE *fp1;
// lots of code...
// mem1, 2, 3, 4 got allocated
// lots of code and condition checks
if (condition_fail ed)
{
// blah blah
// free mem1, mem2, mem3, mem4
return;
}
if (condition2_fai led)
{
// blah blah
// free mem1, mem2, ...
fclose(fp1);
return;
}
// here the end of routine (clean exit code):
// free mem1, mem2, mem3, mem4
}
Usually, I would use compiler specific solution by putting most of the code
in __try() and the clean exit code in _finally() block then to reach the
clean exit code I would invoke __leave.
Or use lables and then goto clean_exit
Any better way, other than goto or compiler specific solution?
--
Elias 10 4125
"lallous" <la*****@lgwm.o rg> wrote in message
news:bt******** ****@ID-161723.news.uni-berlin.de... Hello, ... I have a function like:
void fnc() { char *mem1, *mem2, *mem3, *mem4; FILE *fp1; // lots of code... // mem1, 2, 3, 4 got allocated // lots of code and condition checks if (condition_fail ed) { // blah blah // free mem1, mem2, mem3, mem4 return; }
if (condition2_fai led) { // blah blah // free mem1, mem2, ... fclose(fp1); return; }
// here the end of routine (clean exit code): // free mem1, mem2, mem3, mem4 }
Usually, I would use compiler specific solution by putting most of the
code in __try() and the clean exit code in _finally() block then to reach the clean exit code I would invoke __leave.
Or use lables and then goto clean_exit
Any better way, other than goto or compiler specific solution?
A never ending story... You will get that many replies as many posters there
are on Usenet ;-)
My prefered solution is:
void fnc (void)
{
char * const mem1 = something_that_ allocates_mem1( );
if (mem1)
{
char * const mem2 = something_that_ allocates_mem2( );
if (mem2)
{
/* ...etc. */
free(mem2);
}
free(mem1);
}
}
This has, IMO, two main advantages:
1. It's much clearer, variables are only declared where and when they are
actually used.
2. Memory is freed in the reverse order of allocation, which is usually
considered a good practice (though it should make no difference).
On the other hand, it may get a bit cumbersome if you have too many
variables to clear.
But as I said, it is all merely a matter of style. Use what you think is the
best (or your company coding guidelines dictate you).
Peter
Peter Pichler wrote: "lallous" <la*****@lgwm.o rg> wrote in message news:bt******** ****@ID-161723.news.uni-berlin.de... ... I have a function like:
void fnc() { char *mem1, *mem2, *mem3, *mem4; FILE *fp1; // lots of code... // mem1, 2, 3, 4 got allocated // lots of code and condition checks if (condition_fail ed) { // blah blah // free mem1, mem2, mem3, mem4 return; }
if (condition2_fai led) { // blah blah // free mem1, mem2, ... fclose(fp1); return; }
// here the end of routine (clean exit code): // free mem1, mem2, mem3, mem4 }
.... snip ... A never ending story... You will get that many replies as many posters there are on Usenet ;-)
My prefered solution is:
void fnc (void) { char * const mem1 = something_that_ allocates_mem1( ); if (mem1) { char * const mem2 = something_that_ allocates_mem2( ); if (mem2) { /* ...etc. */ free(mem2); } free(mem1); } }
and my version is:
void fnc(void)
{
char *cp1;
char *cp2;
char *cp3;
/* as needed */
if (!(cp1 = malloc(CP1SIZE) )) goto cp1fail;
else if (!(cp2 = malloc(CP2SIZE) )) goto cp2fail;
else if (!(cp3 = malloc(CP3SIZE) )) goto cp3fail;
else {
/* they all worked - use em */
}
cp3fail:
free(cp3);
cp2fail:
free(cp2);
cp1fail:
free(cp1);
}
which is easily extended/compressed to the things needed. For
cleanup with free we can rework this to eliminate the gotos and
simply use NULL initializations for the cpN, but the above
organization will work with more complex scenarios.
--
Chuck F (cb********@yah oo.com) (cb********@wor ldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home .att.net> USE worldnet address!
CBFalconer <cb********@yah oo.com> wrote in message news:<40******* ********@yahoo. com>... Peter Pichler wrote: "lallous" <la*****@lgwm.o rg> wrote in message news:bt******** ****@ID-161723.news.uni-berlin.de... ... I have a function like:
void fnc() { char *mem1, *mem2, *mem3, *mem4; FILE *fp1; // lots of code... // mem1, 2, 3, 4 got allocated // lots of code and condition checks if (condition_fail ed) { // blah blah // free mem1, mem2, mem3, mem4 return; }
if (condition2_fai led) { // blah blah // free mem1, mem2, ... fclose(fp1); return; }
// here the end of routine (clean exit code): // free mem1, mem2, mem3, mem4 }
... snip ... A never ending story... You will get that many replies as many posters there are on Usenet ;-)
My prefered solution is:
void fnc (void) { char * const mem1 = something_that_ allocates_mem1( ); if (mem1) { char * const mem2 = something_that_ allocates_mem2( ); if (mem2) { /* ...etc. */ free(mem2); } free(mem1); } }
and my version is:
void fnc(void) { char *cp1; char *cp2; char *cp3; /* as needed */
if (!(cp1 = malloc(CP1SIZE) )) goto cp1fail; else if (!(cp2 = malloc(CP2SIZE) )) goto cp2fail; else if (!(cp3 = malloc(CP3SIZE) )) goto cp3fail; else { /* they all worked - use em */ } cp3fail: free(cp3); cp2fail: free(cp2); cp1fail: free(cp1); }
which is easily extended/compressed to the things needed. For cleanup with free we can rework this to eliminate the gotos and simply use NULL initializations for the cpN, but the above organization will work with more complex scenarios.
My question was:
1)I have allocated lots of resources (memory, files, ...)
2)for some conditions other than allocation failures the code will
have to exit and clean up, but instead of cleaning up everytime and
repeating the clean up code, the clean up code must be written once
and called many times by some technique such as 'goto'
// here resources are allocated
// here some condition
if (failed)
{
// cleanup code
}
// some code
// some condition
if (failed2)
{
// same cleanup code as above.....
}
On Mon, 12 Jan 2004 22:00:37 -0800, lallous wrote: Peter Pichler wrote:
> A never ending story... You will get that many replies as many > posters there are on Usenet ;-)
:)
My question was: 1)I have allocated lots of resources (memory, files, ...) 2)for some conditions other than allocation failures the code will have to exit and clean up, but instead of cleaning up everytime and repeating the clean up code, the clean up code must be written once and called many times by some technique such as 'goto'
Initialize all pointers to NULL.
Use true false value to indicate successful allocation of resources where
the handle itself (such as a file handle) can't be used to check if the
resource should be freed. If you detect an error use a goto.
This works for the simple cases, but I'd bet someone could come up with an
example where the method would fail.
int fn() {
char *mem1 = NULL;
char *mem2 = NULL;
char *mem3 = NULL;
char *mem4 = NULL;
FILE *fp1 = NULL;
int some_resource_f lag = 0;
int result;
/* allocate resources, goto cleanup on failure */
cleanup:
if (some_resource_ flag) free_some_resou rce();
if (fp1) fclose(fp1);
free(mem4);
free(mem3);
free(mem2);
free(mem1);
return result;
}
--
NPV
"the large print giveth, and the small print taketh away"
Tom Waits - Step right up
Nils Petter Vaskinn <no@spam.for.me .invalid> wrote in message news:<pa******* *************** ******@spam.for .me.invalid>...
I like all those solutions posted above, and have used them all
myself. What's not covered, however, is leaving the function the way
it is! :-D That's my current 'fave method'. Early programming exits
are supposedly a 'bad thing', but they occasionally have advantages
over the other methods when:
1. The cleanup code to be executed varies from exit to exit.
2. The remaining code is large, and doing it in one of the above
methods results in heavily indented code.
Using the other two methods, it's impossible to be consistent - it's
appropriate only occasionally. The 'early exit' method is useful more
frequently, but sometimes results in the redundant line or two.
In general, if early exits will give me what I want with no duplicate
code, or only one line, I'll use it. If the cleanup code is
significant, I use one of the methods outlined by the others. I prefer
the clean reading style you get with early exits, so I use it most
frequently. This is a change from my C coding style as a beginner.
//----------------------------------
// Here's an example of its use:
//----------------------------------
if (!A)
return; // error condition 1
if (!B)
return; // error condition 2
if (!C)
return; // error condition 3.
// If the code got here, it passed all the tests.
dofunction(D);
//----------------------------------
// Without it, the code would look like:
//----------------------------------
if (A)
if (B)
if (C)
dofunction(D);
else
return;
else
return;
else
return;
In this trivial example, the 'else returns' are optional and can be
left off... but if they're supposed to do cleanup, you can see where
this indentation could get quite large. Also, with this method, it's
easy to lose track of where you are in the 'if' hierarchy, and
inadvertantly execute some logic you weren't supposed to. I haven't
had that problem since switching to the 'early exit' style of
programming.
--Kamilche
On Tue, 13 Jan 2004 02:36:43 -0800, Kamilche wrote: Nils Petter Vaskinn <no@spam.for.me .invalid> wrote in message news:<pa******* *************** ******@spam.for .me.invalid>...
I like all those solutions posted above, and have used them all myself. What's not covered, however, is leaving the function the way it is! :-D That's my current 'fave method'. Early programming exits are supposedly a 'bad thing', but they occasionally have advantages over the other methods when:
1. The cleanup code to be executed varies from exit to exit. 2. The remaining code is large, and doing it in one of the above methods results in heavily indented code.
1. My suggestion to have a flag for each resource to indicate if it should
be freed or not will usually eliminate the need for different cleanups.
Since checking the flags takes care of the different cases
2. The goto method I described above shouldn't increase the indentation
level significantly unless you use a very bizarre style.
Using the other two methods, it's impossible to be consistent - it's appropriate only occasionally. The 'early exit' method is useful more frequently, but sometimes results in the redundant line or two.
In general, if early exits will give me what I want with no duplicate code, or only one line, I'll use it. If the cleanup code is significant, I use one of the methods outlined by the others. I prefer the clean reading style you get with early exits, so I use it most frequently. This is a change from my C coding style as a beginner.
[snip example]
Your early exit exaple doesn't really fit in this discussion since there
is no cleanup.
But "return;" and "return something;" can easily be replaced with
/* result = something if there is a return from the function */
goto cleanup;
If there was any cleanup to be done, so the body of the code would
essentially be the same as with early exit. But you avoid having the
cleanup code at every exit point.
What it all boils down to is trying to make the code easy to understand
and maintain. Your example is, so it's perfectly ok code (IMO) but I would
try to avoid early exit in some other cases (like in one single case
hidden deep within nested ifs and loops where a quick glance at the
function could lead one to believe it has only a single exit point.
--
NPV
"the large print giveth, and the small print taketh away"
Tom Waits - Step right up
lallous wrote: CBFalconer <cb********@yah oo.com> wrote in message news:
.... snip ... and my version is:
void fnc(void) { char *cp1; char *cp2; char *cp3; /* as needed */
if (!(cp1 = malloc(CP1SIZE) )) goto cp1fail; else if (!(cp2 = malloc(CP2SIZE) )) goto cp2fail; else if (!(cp3 = malloc(CP3SIZE) )) goto cp3fail; else { /* they all worked - use em */ } cp3fail: free(cp3); cp2fail: free(cp2); cp1fail: free(cp1); }
which is easily extended/compressed to the things needed. For cleanup with free we can rework this to eliminate the gotos and simply use NULL initializations for the cpN, but the above organization will work with more complex scenarios.
My question was: 1)I have allocated lots of resources (memory, files, ...) 2)for some conditions other than allocation failures the code will have to exit and clean up, but instead of cleaning up everytime and repeating the clean up code, the clean up code must be written once and called many times by some technique such as 'goto'
which is just what my pattern does. malloc/free are just one
examples of routines that setup and cleanup.
if (setupfails(par ams1)) goto clean1;
else if (setupfails(par ams2)) goto clean2;
else {
/* success */
}
clean2: cleanup(params1 );
clean1: cleanup(params2 );
--
Chuck F (cb********@yah oo.com) (cb********@wor ldnet.att.net)
Available for consulting/temporary embedded and systems.
<http://cbfalconer.home .att.net> USE worldnet address!
> void fnc() { char *mem1, *mem2, *mem3, *mem4; FILE *fp1; // lots of code... // mem1, 2, 3, 4 got allocated // lots of code and condition checks if (condition_fail ed) { // blah blah // free mem1, mem2, mem3, mem4 return; }
if (condition2_fai led) { // blah blah // free mem1, mem2, ... fclose(fp1); return; }
// here the end of routine (clean exit code): // free mem1, mem2, mem3, mem4 }
I have a method I use only when I feel it really clarifies the situation,
and I always comment it (with a few words) when I'm doing so. It assumes
that all pointers (or objects in your case) are set to such a state that
cleaning them when left untouched isn't a problem or that it is obvious when
they don't need to be cleaned.
char *mem1 = NULL, *mem2 = NULL, *mem3 = NULL;
/* or you could do this:
char *mem1, *mem2, *mem3;
mem1 = mem2 = mem3 = NULL;
*/
/* try-like exception construct */
do
{
mem1 = malloc(MEM1SIZE );
if ( !mem1 )
break;
/* do something here */
mem2 = malloc(MEM1SIZE );
if ( !mem2 )
break;
/* do something else here */
mem1 = malloc(MEM1SIZE );
if ( !mem3 )
break;
/* do even more here */
}
while ( 0 );
if ( mem1 ) free(mem1);
if ( mem2 ) free(mem2);
if ( mem3 ) free(mem3);
return;
The do { } while ( 0 ) will always be executed once. You could put a return
code in there if you want to as well.
I think it is a decent solutions, much like the goto solution, but the
reason I prefer this over the goto approach is because it is very obvious
what block of code is being "tried" and it bears a little more resemblance
to a real try/catch construct.
Hope this helps,
Martijn Haak http://www.sereneconcepts.nl
Nils Petter Vaskinn <no@spam.for.me .invalid> wrote in message news:<pa******* *************** ******@spam.for .me.invalid>... What it all boils down to is trying to make the code easy to understand and maintain. Your example is, so it's perfectly ok code (IMO) but I would try to avoid early exit in some other cases (like in one single case hidden deep within nested ifs and loops where a quick glance at the function could lead one to believe it has only a single exit point.
Yeah, consistency with the rest of the code is important! I use early
exits very frequently in a common set of modules, so when you're
reading it, exceptions are pulled out and 'legal code' is in a
straight line down the page. But if the code didn't use early exits so
heavily, I would hesitate to include it - it's best to follow the
convention of the existing codebase.
I read about a study they did on experienced programmers versus newbie
programmers. As long as the code did 'the expected thing' and followed
a convention of some sort, the experienced programmers were far more
productive. But if the code did it one way in this module, another way
in another module, and was relatively a mishmash, they were just as
unproductive as the newbie programmers.
Far from being the 'hobgoblin of little minds', consistency extends a
programmer's brainpower. Use it in the style most suited to YOUR
brain. :-)
--Kamilche This thread has been closed and replies have been disabled. Please start a new discussion. Similar topics |
by: Jason |
last post by:
I have a number of arrays that are populated with database values. I
need to determine which array has the highest ubound out of all the
arrays. The array size will always change based on the database
record. Therefore, I need to be able to throw the arrays into a
function that will automatically determine the highest ubound array.
I was wondering if anyone might have a clean function that can do
this. I have created a function that...
|
by: lallous |
last post by:
Hello,
I have a function like:
void fnc() {
char *mem1, *mem2, *mem3, *mem4;
// lots of code...
// mem1, 2, 3, 4 got allocated
// lots of code and condition checks
if (condition_failed)
|
by: Steve Jorgensen |
last post by:
Hi all,
I had just participating in a small thread here about when to set recordset
variables to Nothing when I ran into an interesting case in my own code that
highlighted the need for a formal, centralized function to deal with this.
The case that came up was that I have a class module that handles 2 recordsets
that it must clean up at termination, but the termination should not assume
that the recordsets have necessarily been...
|
by: Felix Kater |
last post by:
Hi,
when I need to execute a general clean-up procedure (inside of a
function) just before the function returns -- how do I do that when
there are several returns spread over the whole function?
My first approach: Use "while(1)" and "break", however this doesn't work
if there is another loop inside (since I can't break two loops at the
same time):
|
by: Rick |
last post by:
Hello,
Below I create a static instance of an object, works well.
public static BasicCounter GlobalCounter = new
BasicCounter("GlobalCounter");
private void Page_Load(object sender, System.EventArgs e)
{
GlobalCounter.Increment();
| |
by: cj |
last post by:
I want when someone clicks the X in the upper right corner of my program
for it to run the sub I've put in for the exit item on the main menu
(exitMenuItem_click)
|
by: robert maas, see http://tinyurl.com/uh3t |
last post by:
I'm working on examples of programming in several languages, all
(except PHP) running under CGI so that I can show both the source
files and the actually running of the examples online. The first
set of examples, after decoding the HTML FORM contents, merely
verifies the text within a field to make sure it is a valid
representation of an integer, without any junk thrown in, i.e. it
must satisfy the regular expression: ^ *?+ *$
If the...
|
by: Ben |
last post by:
Hi
We are looking for a component that offers that offers the below for Tiff
files:
Image clean-up (deskew, despeckle)
Printing capabilities from VB
The ability to add text to image, e.g. time / date
Nice to have:
|
by: teddysnips |
last post by:
This is sort of an addendum to my previous post entitled: "Restrict FE
application to one user at a time".
My preferred design is to have a table with a single row that contains
the network name of the person currently connected to the database.
The existence of the row will serve a) to allow the system to bump any
other user who wishes to connect, and b) to inform such users of the
name of the currently logged-on user.
However, at...
|
by: marktang |
last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main usage, and What is the difference between ONU and Router. Let’s take a closer look !
Part I. Meaning of...
|
by: Hystou |
last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can effortlessly switch the default language on Windows 10 without reinstalling. I'll walk you through it.
First, let's disable language synchronization. With a Microsoft account, language settings sync across devices. To prevent any complications,...
| |
by: Oralloy |
last post by:
Hello folks,
I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>".
The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed.
This is as boiled down as I can make it.
Here is my compilation command:
g++-12 -std=c++20 -Wnarrowing bit_field.cpp
Here is the code in...
|
by: Hystou |
last post by:
Overview:
Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
|
by: tracyyun |
last post by:
Dear forum friends,
With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
|
by: TSSRALBI |
last post by:
Hello
I'm a network technician in training and I need your help.
I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs.
The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols.
I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
|
by: adsilva |
last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
|
by: muto222 |
last post by:
How can i add a mobile payment intergratation into php mysql website.
| |
by: bsmnconsultancy |
last post by:
In today's digital era, a well-designed website is crucial for businesses looking to succeed. Whether you're a small business owner or a large corporation in Toronto, having a strong online presence can significantly impact your brand's success. BSMN Consultancy, a leader in Website Development in Toronto offers valuable insights into creating effective websites that not only look great but also perform exceptionally well. In this comprehensive...
| |