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)
{
// blah blah
// free mem1, mem2, mem3, mem4
return;
}
if (condition2_failed)
{
// blah blah
// free mem1, mem2, ...
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 15 2330
lallous wrote: 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) { // blah blah // free mem1, mem2, mem3, mem4 return; }
if (condition2_failed) { // blah blah // free mem1, mem2, ... 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?
use a std::string instead of dynamically allocated character arrays.
#include <string>
void fnc()
{
std::string mem1;
std::string mem2;
mem1 = "Hallo";
mem2 = "World";
// look Ma! I don't have to do anything. mem1 and mem2
// will free the allocated memory all by themselfs
}
--
Karl Heinz Buchegger kb******@gascad.at
"Karl Heinz Buchegger" <kb******@gascad.at> wrote in message
news:3F***************@gascad.at... lallous wrote: 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) { // blah blah // free mem1, mem2, mem3, mem4 return; }
if (condition2_failed) { // blah blah // free mem1, mem2, ... 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?
use a std::string instead of dynamically allocated character arrays.
#include <string>
void fnc() { std::string mem1; std::string mem2;
mem1 = "Hallo"; mem2 = "World";
// look Ma! I don't have to do anything. mem1 and mem2 // will free the allocated memory all by themselfs }
-- Karl Heinz Buchegger kb******@gascad.at
Hello,
Your solution is a hint...but I am using such buffers to do file i/o and
cannot really use std::string....
And sometimes I have code like:
fclose(fp1); fclose(fp2); free(mem1); myObj->DeInit(); blah blah...
So you see how the cleanup code is not always solved by using objects...so
my question was how to avoid repeating the cleanup code over and over in
case I want to return in the middle of the function.
--
Elias
"lallous" <la*****@lgwm.org> wrote in message
news:bt************@ID-161723.news.uni-berlin.de... 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) { // blah blah // free mem1, mem2, mem3, mem4 return; }
if (condition2_failed) { // blah blah // free mem1, mem2, ... 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?
The problem with code you posted is code duplication (= maintenance
headache, which will no doubt lead to bugs later) and that it is not
exception safe.
If it is just freeing char* that is bothering you, why not use the
std::string class?
#include <string>
void fnc()
{
std::string mem1, mem2, mem3, mem4;
// lots of code...
// lots of code and condition checks
if (condition_failed)
{
// blah blah
// No need to explicitly free mem1, mem2, mem3, mem4!
return;
}
if (condition2_failed)
{
// blah blah
// No need to explicitly free mem1, mem2, mem3, mem4!
return;
}
// No need to explicitly free mem1, mem2, mem3, mem4!
}
The advantage of this is not only that all memory used by the string is
automatically released, no matter how the function exits (return or
exception), but also that string manipulation with the std::string is much
easier to code and understand. Similary the std::vector class is an
excellent replacement for dynamically created arrays; also with this class
there is no need to worry about explicit memory management.
For other tasks that need to be done when a functions exits, consider using
the RAII idiom
( http://c2.com/cgi/wiki?ResourceAcqui...nitialization). An example of
RAII is the std::auto_ptr class. The basic idea of the RAII idiom is to
create a local object which has a destructor that perfoms the operations
necessary when the function is exited (the destructor essentially replaces
the non-standard _finally clause). Since the destructor of local objects is
always called when the function exists, the destructor can perfom the
things you now do in the non-standard _finally() clause.
#include <iostream>
class AutoCleanup
{
public:
AutoCleanup();
~AutoCleanup()
{
std::cout << "AutoCleanup dtor" << std::endl
}
}
void fnc()
{
AutoCleanup tmp;
// lots of code and condition checks
if (condition_failed)
{
// The return statement causes
// AutoCleanup::~AutoCleanup to be called
return;
}
if (condition2_failed)
{
// The return statement causes
// AutoCleanup::~AutoCleanup to be called
return;
}
// When the function finishes
// AutoCleanup::~AutoCleanup will be called
}
Also when a exception is thrown the AutoCleanup::~AutoCleanup will be
called. The RAII idiom is a very handy technique which usefullness is not
restricted to releasing memory or other resources. For example for UI code
you could make a class the changes the mouse cursor to a hourglass on
construction and restores the previous mouse cursor on destruction:
class HourGlassCursor
{
public:
HourGlassCursor() : prev_(getCursor())
{
setCursor(crHourGlass);
}
~HourGlassCursor()
{
setCursor(prev_);
};
private:
Cursor prev_;
};
void calculate()
{
HourGlassCursor hgc;
// do some lengthy processing...
}
The cursor will always be restored, even if an exception is thrown.
--
Peter van Merkerk
peter.van.merkerk(at)dse.nl
lallous wrote: Hello,
I have a function like: ...
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?
Putting your function into a class and writing an additional member function
cleanup() to close files and delete the buffers would help. Addionally you
could write a class (called eg. Buffer) to encapsule your char buffers and
use auto_ptr<Buffer> in your code then.
--
To get my real email adress, remove the two onkas
--
Dipl.-Inform. Hendrik Belitz
Central Institute of Electronics
Research Center Juelich
lallous wrote: 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) { // blah blah // free mem1, mem2, mem3, mem4 return; }
if (condition2_failed) { // blah blah // free mem1, mem2, ... 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
Put the cleanup code in the destructor of an automatic variable. The
resource acquisition probably should be done in a member initialization
list, too. Google. for RAII.
#include <cstddef>
template< typename T >
struct Mem
{
Mem( size_t z ): p( new T [ z ] ) { }
~Mem( ) { /* "blah blah," as you say. */ delete [ ] p; }
T* p;
private:
Mem( Mem const& ) { /* Don't copy the Mem objects. */ }
};
void fnc( )
{
// lots of code...
Mem< char > mem1, mem2, mem3, mem4;
// lots of code and condition checks
if (condition_failed)
{
return;
}
if (condition2_failed)
{
return;
}
// here the end of routine
}
In article <bt************@ID-161723.news.uni-berlin.de>, lallous wrote: "Karl Heinz Buchegger" <kb******@gascad.at> wrote in message news:3F***************@gascad.at...
Your solution is a hint...but I am using such buffers to do file i/o and cannot really use std::string....
And sometimes I have code like: fclose(fp1); fclose(fp2); free(mem1); myObj->DeInit(); blah blah...
So use your own buffer class that wraps a pointer to the dynamic string:
class buf {
char* mem;
public:
buf():mem(NULL) {}
buf (const char* x, int len) : mem (new char[len]) {
copy(x,x+len,mem);
}
void clear() { delete[] mem; mem = NULL; }
~buf() { delete [] mem; }
};
class Foo
{
FILE * fp1, *fp2;
auto_ptr<myObj> myObj;
Foo& operator=(const Foo&); // disable copy construct and assign
Foo(const Foo&);
public:
~Foo() {
fclose(fp1); fclose(fp2); buf.clear(); myObj->DeInit();
...
...
};
If you want your code to be exception safe, it would probably be a good idea
to wrap your file pointer in a class that handles closing the files too.
So you see how the cleanup code is not always solved by using objects...so
Yes it is. You just need the right object.
Cheers,
--
Donovan Rebbechi http://pegasus.rutgers.edu/~elflord/
lallous wrote:
Hello,
Your solution is a hint...but I am using such buffers to do file i/o and cannot really use std::string....
then use something else which has the same semantics (destroy dynamically
allocated memory when the object goes out of scope)
#include <vector>
void fnc()
{
std::vector<unsigned char> mem1;
std::vector<unsigned char> mem2;
mem1.resize( 200 ); // tell mem1 that I need 2 unsigned chars
mem2.resize( 500 ); // and mem2 will need 500 unsigned chars
mem1[20] = 5;
mem2[80] = 8;
// look Ma! I don't have to do anything. mem1 and mem2
// will free the allocated memory all by themselfs
}
And sometimes I have code like: fclose(fp1); fclose(fp2); free(mem1); myObj->DeInit(); blah blah... So you see how the cleanup code is not always solved by using objects...
It can *always* be solved by putting the thing you need to manage into
a class of its own. In fact that is the whole point of the RAII
idiom. The destructor gets called when the object goes out of scope
no matter how this is achieved. And the destructor is responsible for
deleting the dynamically managed resource (be it some memory, or a file
handle, or a modem or whatever).
so my question was how to avoid repeating the cleanup code over and over in case I want to return in the middle of the function.
Encapsulate the resource in a class and put the cleanup code into the destructor.
For some common types of resources this has already be done in your library,
eg std::string, std::vector, std::map, io streams, etc..
--
Karl Heinz Buchegger kb******@gascad.at
On Fri, 9 Jan 2004 14:27:29 +0200, "lallous" <la*****@lgwm.org> wrote: Your solution is a hint...but I am using such buffers to do file i/o and cannot really use std::string....
And sometimes I have code like: fclose(fp1); fclose(fp2); free(mem1); myObj->DeInit(); blah blah...
shared_ptr<FILE> fp1(fopen("Filename", "r+"), fclose);
shared_ptr<MyObject> myObj(myObj, mem_fn(&MyObject::DeInit));
So you see how the cleanup code is not always solved by using objects...so my question was how to avoid repeating the cleanup code over and over in case I want to return in the middle of the function.
Use some kind of scope guard class. boost::shared_ptr is good for most
uses (particularly when combined with boost::bind and boost::mem_fn).
You might prefer an alternative such as: http://www.cuj.com/documents/s=8000/...p1812alexandr/
Note that there should soon be std::shared_ptr, std::bind and
std::mem_fn - they are already in the draft standard library
extension.
Tom
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
On Fri, 09 Jan 2004 14:14:28 +0100 in comp.lang.c++, Hendrik Belitz
<ho**************@fz-juelich.de> was alleged to have written: could write a class (called eg. Buffer) to encapsule your char buffers and use auto_ptr<Buffer> in your code then.
std::auto_ptr<> cannot be used for this purpose because it uses "delete"
of the owned pointer, and not "delete[]"
"tom_usenet" <to********@hotmail.com> wrote in message
news:0s********************************@4ax.com... On Fri, 9 Jan 2004 14:27:29 +0200, "lallous" <la*****@lgwm.org> wrote:
Your solution is a hint...but I am using such buffers to do file i/o and cannot really use std::string....
And sometimes I have code like: fclose(fp1); fclose(fp2); free(mem1); myObj->DeInit(); blah blah...
shared_ptr<FILE> fp1(fopen("Filename", "r+"), fclose);
shared_ptr<MyObject> myObj(myObj, mem_fn(&MyObject::DeInit));
So you see how the cleanup code is not always solved by using
objects...somy question was how to avoid repeating the cleanup code over and over in case I want to return in the middle of the function.
Use some kind of scope guard class. boost::shared_ptr is good for most uses (particularly when combined with boost::bind and boost::mem_fn). You might prefer an alternative such as:
http://www.cuj.com/documents/s=8000/...p1812alexandr/
Note that there should soon be std::shared_ptr, std::bind and std::mem_fn - they are already in the draft standard library extension.
Tom
C++ FAQ: http://www.parashift.com/c++-faq-lite/ C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Thanks to all who shared their comments.
I liked most the vector<char> instead of allocating a char * w/ new char[].
Also liked the shared_ptr<FILE> ... .
I am still new to C++ and was expecting some solution that doesn't involve
objects as the STD library and other objects are loaded with lots of code
and checking which makes the code a bit slower.
Will ask this again in comp.lang.c to get yet more approaches.
--
Elias
On Mon, 12 Jan 2004 17:15:19 +0200, "lallous" <la*****@lgwm.org>
wrote: Thanks to all who shared their comments.
I liked most the vector<char> instead of allocating a char * w/ new char[]. Also liked the shared_ptr<FILE> ... .
I am still new to C++ and was expecting some solution that doesn't involve objects as the STD library and other objects are loaded with lots of code and checking which makes the code a bit slower.
Code using standard libraries tends to be faster than code that
doesn't. Matching the optimization effort your library implementor has
gone to for the general case container can be hard even for a specific
case. In any case, the work is generally not worth it - improving
algorithms typically gives you more of a speed up.
Tom
C++ FAQ: http://www.parashift.com/c++-faq-lite/
C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
lallous wrote: I liked most the vector<char> instead of allocating a char * w/ new char[]. Also liked the shared_ptr<FILE> ... .
I am still new to C++ and was expecting some solution that doesn't involve objects as the STD library
Then you are reinventing the wheel for no good reason.
and other objects are loaded with lots of code and checking which makes the code a bit slower.
I bet that you will not be able to beat the performance of std::vector
(If used right) with homegrown code by more then 5%. Will ask this again in comp.lang.c to get yet more approaches.
-- Elias
--
Karl Heinz Buchegger kb******@gascad.at
> 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) // (etc.)
Assuming you don't like the suggestions offered so far (ie. create
a class where your cleanup code runs in the destructor), you
could do this:
void fnc() {
char *mem1 = 0, *mem2 = 0, *mem3 = 0, *mem4 = 0;
try {
// lots of code
if (condition1_failed) {
// condition1-specific cleanup code
}
}
delete mem1; delete mem2; delete mem3; delete mem4;
}
There is actually no need for __finally and __leave, you can
always structure your function so that "try" and "catch" are
sufficient.
"lallous" <la*****@lgwm.org> wrote in message news:<bt************@ID-161723.news.uni-berlin.de>...
[snip] Any better way, other than goto or compiler specific solution?
Just in case nobody explicitly stated the rule to apply here.
Resource allocation should usually happen in a class.
Resource de-allocation should usually happen in the dtor of a class.
This applies not just to memory, but files, and anything else
that has to be allocated, gotten, initialized, etc. So when
you get into things like networking, for example, and you
have to open a connection, that should be done in a class and
given back in the dtor.
Then you create an instance of a class and have that object do
the allocation. When the object goes out of scope, the dealloc
hapens automatically. This will work properly wether it happens
because you returned normally form the function, or because you
trapped an error and aborted, or because some sub-component
threw an exception.
The advantages of this are many. For example, you can now start
working on making your code exception safe. You can have your
functions throw exceptions and catch them with some assurance
that you won't have resource leaks. And you won't have to struggle
to remember all the stuff you allocated, and in what order,
so you can deallocate it on error conditions.
This is why so many folks were suggesting you use the std string
objects. (Well, one reason.)
Socks
"lallous" <la*****@lgwm.org> wrote in message
news:bt************@ID-161723.news.uni-berlin.de... "tom_usenet" <to********@hotmail.com> wrote in message news:0s********************************@4ax.com... On Fri, 9 Jan 2004 14:27:29 +0200, "lallous" <la*****@lgwm.org> wrote:
Your solution is a hint...but I am using such buffers to do file i/o
andcannot really use std::string....
And sometimes I have code like: fclose(fp1); fclose(fp2); free(mem1); myObj->DeInit(); blah blah... shared_ptr<FILE> fp1(fopen("Filename", "r+"), fclose);
shared_ptr<MyObject> myObj(myObj, mem_fn(&MyObject::DeInit));
So you see how the cleanup code is not always solved by using objects...somy question was how to avoid repeating the cleanup code over and over
incase I want to return in the middle of the function.
Use some kind of scope guard class. boost::shared_ptr is good for most uses (particularly when combined with boost::bind and boost::mem_fn). You might prefer an alternative such as:
http://www.cuj.com/documents/s=8000/...p1812alexandr/
Note that there should soon be std::shared_ptr, std::bind and std::mem_fn - they are already in the draft standard library extension.
Tom
C++ FAQ: http://www.parashift.com/c++-faq-lite/ C FAQ: http://www.eskimo.com/~scs/C-faq/top.html
Thanks to all who shared their comments.
I liked most the vector<char> instead of allocating a char * w/ new
char[]. Also liked the shared_ptr<FILE> ... .
I am still new to C++ and was expecting some solution that doesn't involve objects as the STD library and other objects are loaded with lots of code and checking which makes the code a bit slower.
"lots of <source> code" != "lots of machine instructions" - atleast in C++ -
release/optimized builds with any good compiler will only generate the code
that's actually used.
Will ask this again in comp.lang.c to get yet more approaches.
Sounds like this was your predisposition anyway.
Jeff F 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...
|
by: lallous |
last post by:
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...
|
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?...
|
by: Stefan Krah |
last post by:
Hello,
I'm trying to run a Python script as a Windows service with a defined
shutdown. The script (enigma-client.py) handles the communications with
the server in a distributed computing effort...
|
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....
|
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...
|
by: Simon |
last post by:
As title. How to clean out VSWebCache? Any good way to do that?
Thanks.
|
by: mathieu |
last post by:
Hi there,
I am trying to reuse a piece of code that was designed as an
application. The code is covered with 'exit' calls. I would like to
reuse it as a library. For that I renamed the 'main'...
|
by: taylorcarr |
last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
|
by: Charles Arthur |
last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
|
by: ryjfgjl |
last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
|
by: nemocccc |
last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
|
by: Sonnysonu |
last post by:
This is the data of csv file
1 2 3
1 2 3
1 2 3
1 2 3
2 3
2 3
3
the lengths should be different i have to store the data by column-wise with in the specific length.
suppose the i have to...
|
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,...
|
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...
|
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,...
|
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...
| |