Better way of allocating a memory( auto_ptr vs new vs malloc)

A

Ami

Friends

I have been working on C++ code optimization to minimize the memory
leaks and better performance on HP-UX with aCC
I have the following example to share with you

I have a structure SYS_LC_DETAILS_CDA for which I have allocated a
memory using malloc and then memset and then calling a function to
assign values to the structure elements as below
SYS_LC_DETAILS_CDA *p_str_lc_details = (SYS_LC_DETAILS_CDA *)malloc
(sizeof(SYS_LC_DETAILS_CDA));
memset(p_str_lc_details,'\0',sizeof(SYS_LC_DETAILS_CDA));
conObj.CopyToDceSYS_LC_DETAILS_CDA(p_str_lc_details,pStrLcDetails);
and calling free()

in another example
im using a new operator as below
SYS_LC_DETAILS_CDA *p_str_lc_details = new SYS_LC_DETAILS_CDA ;
memset(p_str_lc_details,'\0',sizeof(SYS_LC_DETAILS_CDA));
conObj.CopyToDceSYS_LC_DETAILS_CDA(p_str_lc_details,pStrLcDetails);
then delete

in a 3rd way
I do as below
SYS_LC_DETAILS_CDA p_str_lc_details;
memset(&p_str_lc_details,'\0',sizeof(SYS_LC_DETAILS_CDA));
in above case I dont have to deallocate any...

in a 4th way I am using an auto_ptr as below
auto_ptr<SYS_LC_DETAILS_CDA>p_str_lc_details = (new
SYS_LC_DETAILS_CDA) ;
and then passing the pointer variable as
conObj.CopyToDceSYS_LC_DETAILS_CDA(p_str_lc_details,pStrLcDetails);

Which is the better way of allocating . auto_ptr score well above the
rest as the object gets destroyed as soon as it goes out of scope ...

So which is the best way to minimize the meamory leaks ?

Many thanks
 
P

peter koch

Friends

I have been working on C++  code optimization to minimize the memory
leaks and better performance on HP-UX with aCC
 I have the following example to share with you

I have a structure  SYS_LC_DETAILS_CDA  for which I have allocated  a
memory using malloc  and then memset and then calling a function to
assign values to the structure elements as  below
  SYS_LC_DETAILS_CDA *p_str_lc_details = (SYS_LC_DETAILS_CDA *)malloc
(sizeof(SYS_LC_DETAILS_CDA));
 memset(p_str_lc_details,'\0',sizeof(SYS_LC_DETAILS_CDA));
conObj.CopyToDceSYS_LC_DETAILS_CDA(p_str_lc_details,pStrLcDetails);
and calling free()

This is the C way. I can't really recommend it.
in another example
im using a new operator as below
 SYS_LC_DETAILS_CDA *p_str_lc_details = new  SYS_LC_DETAILS_CDA ;

This is the standard way to allocate dynamic memory in C++. You just
forgot to default initialise it (using new SYS_LC_DETAILS_CDA()). This
would let you forget the memset (another C-function, you'd do better
to forget). You have a potential resource leak, however, which could
be avoided e.g. by using std::auto_ptr as you mention later.
 memset(p_str_lc_details,'\0',sizeof(SYS_LC_DETAILS_CDA));
conObj.CopyToDceSYS_LC_DETAILS_CDA(p_str_lc_details,pStrLcDetails);
then delete

in a 3rd way
I do as below
SYS_LC_DETAILS_CDA p_str_lc_details;
 memset(&p_str_lc_details,'\0',sizeof(SYS_LC_DETAILS_CDA));

This is the correct way whenever you don't need dynamic memory. Always
use this. And again, you should avoid the memset by using default
initialisation - but beware: you need to use
SYS_LC_DETAILS_CDA p_str_lc_details(SYS_LC_DETAILS_CDA());

and not
SYS_LC_DETAILS_CDA p_str_lc_details();

as this is a function declaration.
in above case I dont have to deallocate any...

in a 4th way I am using an auto_ptr as below
auto_ptr<SYS_LC_DETAILS_CDA>p_str_lc_details = (new
SYS_LC_DETAILS_CDA) ;
and then passing the pointer variable as
conObj.CopyToDceSYS_LC_DETAILS_CDA(p_str_lc_details,pStrLcDetails);

In the above case, the second one is clearly the best. Otherwise -
when the object must outlive scope - the std::auto_ptr solution or
something similar should be preferred.

/Peter
 
A

Ami

Thanks Peter

I have few qustions
Consider the allocation SYS_LC_DETAILS_CDA p_str_lc_details
(SYS_LC_DETAILS_CDA());
SYS_LC_DETAILS_CDA() in above would do default initialization right
then I can safely avoid the use of C style memset..
and then nevere have to de allocate the same.

As far as auto_ptr is concrned , do I again need to initialize to
SYS_LC_DETAILS_CDA () as shown below
auto_ptr<SYS_LC_DETAILS_CDA>p_str_lc_details = (new SYS_LC_DETAILS_CDA
()) ;
another major concerned abt using auto_ptr is

after the memory allocation is done tht is lets say
int main ()
{

auto_ptr<SYS_LC_DETAILS_CDA>p_str_lc_details = (new SYS_LC_DETAILS_CDA
()) ;
conObj.CopyToDceSYS_LC_DETAILS_CDA(p_str_lc_details.get
(),pStrLcDetails); //
return ( EXIT_SUCESS);
}

void CopyToDceSYS_LC_DETAILS_CDA(SYS_LC_DETAILS_CDA *output)
{
// some code
}

do u see any problem with uisng an auto pointer like above i.e passing
as an argument in a function call .
Is there any memory Leak ?
I think the auto of auto ptr is the best way ..
Also in the code the malloc is done like
SYS_GUARANTORS_CDA *p_str_guarantors = (SYS_GUARANTORS_CDA *)malloc
(sizeof(SYS_GUARANTORS_CDA)*(p_nbr_Guarantors+1));
so using new for above is like
SYS_GUARANTORS_CDA *p_str_guarantors = (SYS_GUARANTORS_CDA *)new char
[sizeof(SYS_GUARANTORS_CDA)*(p_nbr_Guarantors+1)];
is the above correct way i.e using an array

Thanks
 
E

Erik Wikström

Ami wrote:
My god that is so hard to read. Look at the difference a couple of
find-and-replaces and some indention do:

And it lets us find some things to improve upon.

T p(); will do just as well.

No problem at all, but you might want to consider using a shared pointer
and pass that instead of using get(). Or pass a reference to the auto ptr.

No, but there is always the risk that func() will somehow save the
pointer you pass in and someone else will later try to access it.

I'm not sure how it is in C++, but in C you do not have to cast the
result of malloc.
so using new for above is like

T *p = (T *)new char [sizeof(T)*(n+1)];

T* p = new T[n+1];
 
J

James Kanze

I have been working on C++  code optimization to minimize the
memory leaks and better performance on HP-UX with aCC
 I have the following example to share with you
I have a structure  SYS_LC_DETAILS_CDA  for which I have
allocated  a memory using malloc  and then memset and then
calling a function to assign values to the structure elements
as  below
  SYS_LC_DETAILS_CDA *p_str_lc_details = (SYS_LC_DETAILS_CDA *)malloc
(sizeof(SYS_LC_DETAILS_CDA));
 memset(p_str_lc_details,'\0',sizeof(SYS_LC_DETAILS_CDA));
conObj.CopyToDceSYS_LC_DETAILS_CDA(p_str_lc_details,pStrLcDetails);
and calling free()
in another example im using a new operator as below
 SYS_LC_DETAILS_CDA *p_str_lc_details = new  SYS_LC_DETAILS_CDA ;
 memset(p_str_lc_details,'\0',sizeof(SYS_LC_DETAILS_CDA));
conObj.CopyToDceSYS_LC_DETAILS_CDA(p_str_lc_details,pStrLcDetails);
then delete

Why the memset? Why not a constructor?

Even in C, memset is NOT the preferred solution; it's much
better to define a static instance of the struct, and assign it.
in a 3rd way I do as below
SYS_LC_DETAILS_CDA p_str_lc_details;
 memset(&p_str_lc_details,'\0',sizeof(SYS_LC_DETAILS_CDA));
in above case I dont have to deallocate any...

The semantics are not the same. If the value has automatic
lifetime, using dynamic allocation is an abberation which should
be avoided at all costs.
in a 4th way I am using an auto_ptr as below
auto_ptr<SYS_LC_DETAILS_CDA>p_str_lc_details = (new
SYS_LC_DETAILS_CDA) ;
and then passing the pointer variable as
conObj.CopyToDceSYS_LC_DETAILS_CDA(p_str_lc_details,pStrLcDetails);
Which is the better way of allocating . auto_ptr score  well
above the rest as the object gets destroyed as soon as it goes
out of scope ...
So which is the best way to minimize the meamory leaks ?

Automatic variables for automatic lifetime.
 
J

James Kanze

On 2008-12-06 23:36, blargg wrote:
And it lets us find some things to improve upon.
  T p(); will do just as well.

Not at local scope (which IIRC was the case). At local scope,
that declares a function.
No need to use () around the new, auto_ptr<T>p = new T();
works just as fine.

It shouldn't. At least according to C++98. (I don't have a
copy of the C++03 standard here.) There's no assignment
operator of auto_ptr which takes a T*, and there's no implicit
conversion.
No problem at all, but you might want to consider using a
shared pointer and pass that instead of using get(). Or pass a
reference to the auto ptr.

Or pass a reference to the object, using *p in the calling
function. (Unless the called function is capable of handling a
null pointer, this is the preferred solution.)
No, but there is always the risk that func() will somehow save
the pointer you pass in and someone else will later try to
access it.
I'm not sure how it is in C++, but in C you do not have to
cast the result of malloc.

In C++, you do.
so using new for above is like
  T *p = (T *)new char [sizeof(T)*(n+1)];
  T* p = new T[n+1];

Just a reminder, too. You can't use std::auto_ptr with array
new. In C++, the preferred solution for this would be:

std::vector< char > obj( sizeof(T)*(n+1) ) ;

(Except that I suspect that what he wants is:

std::vector< T > obj( n + 1 ) ;

..)
 
A

Ami

And it lets us find some things to improve upon.
  T p(); will do just as well.

Not at local scope (which IIRC was the case).  At local scope,
that declares a function.
No need to use () around the new, auto_ptr<T>p = new T();
works just as fine.

It shouldn't.  At least according to C++98.  (I don't have a
copy of the C++03 standard here.)  There's no assignment
operator of auto_ptr which takes a T*, and there's no implicit
conversion.




No problem at all, but you might want to consider using a
shared pointer and pass that instead of using get(). Or pass a
reference to the auto ptr.

Or pass a reference to the object, using *p in the calling
function.  (Unless the called function is capable of handling a
null pointer, this is the preferred solution.)
No, but there is always the risk that func() will somehow save
the pointer you pass in and someone else will later try to
access it.
I'm not sure how it is in C++, but in C you do not have to
cast the result of malloc.

In C++, you do.
so using new for above is like
  T *p = (T *)new char [sizeof(T)*(n+1)];
  T* p = new T[n+1];

Just a reminder, too.  You can't use std::auto_ptr with array
new.  In C++, the preferred solution for this would be:

    std::vector< char > obj( sizeof(T)*(n+1) ) ;

(Except that I suspect that what he wants is:

    std::vector< T > obj( n + 1 ) ;

.)

--
James Kanze (GABI Software)             email:[email protected]
Conseils en informatique orientée objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34- Hide quoted text -

- Show quoted text -

Thanks James and Eric for the explanation.. I have few questions
Eric you mention about passing a reference to the auto ptr for example
in the sample code , I have got now
int main ()
{
auto_ptr<T>p = (new T()) ;
func(&(p.get())); // Im passing a reference to the auto _ptr
p.release(); // Would free up
return ( EXIT_SUCESS);
}
void func(T *output)
{
output->do_Something();
}

Now if there is any exception gets thrown in the func()
what would be the behaviour of auto _ptr ??

Also in a function call please correct me if I am wrong
I can use * as func(*(p.get()));
correct ?

James .. My another question is
for allocating a memory to an array of structures
You mentioned about using vector like below
int main ()
{
std::vector< T > obj( n + 1 ) ;
func(obj);
return(EXIT_SUCCESS);
}
void func(&obj)
{
obj->do_Something();
}

if any exception is thrown in func() .. what will the end result ?

Many Thanks for your time
 
A

Ami

Not at local scope (which IIRC was the case).  At local scope,
that declares a function.
It shouldn't.  At least according to C++98.  (I don't have a
copy of the C++03 standard here.)  There's no assignment
operator of auto_ptr which takes a T*, and there's no implicit
conversion.
Or pass a reference to the object, using *p in the calling
function.  (Unless the called function is capable of handling a
null pointer, this is the preferred solution.)
In C++, you do.
so using new for above is like
  T *p = (T *)new char [sizeof(T)*(n+1)];
  T* p = new T[n+1];
Just a reminder, too.  You can't use std::auto_ptr with array
new.  In C++, the preferred solution for this would be:
    std::vector< char > obj( sizeof(T)*(n+1) ) ;
(Except that I suspect that what he wants is:
    std::vector< T > obj( n + 1 ) ;

--
James Kanze (GABI Software)             email:[email protected]
Conseils en informatique orientée objet/
                   Beratung in objektorientierter Datenverarbeitung
9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34- Hide quoted text -
- Show quoted text -

Thanks James and Eric for the explanation.. I have few questions
Eric you mention about passing a reference to the auto ptr for example
in the sample code , I have got now
int main ()
   {
       auto_ptr<T>p = (new T()) ;
       func(&(p.get())); // Im passing a reference to the auto _ptr
       p.release(); // Would free up
       return ( EXIT_SUCESS);
   }
   void func(T *output)
   {
     output->do_Something();
   }

Now if there is any exception gets thrown in the func()
what would be the behaviour of auto _ptr ??

Also in a function call please correct me if I am wrong
I can use * as  func(*(p.get()));
correct ?

James .. My another question is
for allocating a memory to an array of structures
You mentioned about using vector like below
int main ()
{
std::vector< T > obj( n + 1 ) ;
func(obj);
return(EXIT_SUCCESS);}

void func(&obj)
{
  obj->do_Something();

}

if any exception is thrown in func() .. what will the end result ?

Many Thanks for your time- Hide quoted text -

- Show quoted text -

This is what I have now .. to overcome the flaw of passing by
value ...
Now I have
int main ()
{
auto_ptr<T>p = (new T()) ;
func(p); // appending get() wont work in a function call
p.release();
return ( EXIT_SUCESS);
}
void func(const auto_ptr<T> &output)
{
output->do_Something();
}

works just fine..
Can you please let me know if this is the best way of passing auto_ptr
by reference and avoiding any leaks ?
also why get() doesnt work in a function call func(p.get()) // throws
error

Many Thanks
 
J

James Kanze

Thanks James and Eric for the explanation.. I have few
questions Eric you mention about passing a reference to the
auto ptr for example in the sample code , I have got now
int main ()
{
auto_ptr<T>p = (new T()) ;
func(&(p.get())); // Im passing a reference to the auto _ptr

That particular line shouldn't compile. p.get() returns a
temporary with pointer type, and the address of operator isn't
legal on temporarires. If it were legal, of course, the results
would have type T**.

(Technically---and you probably should learn the technical
vocabulary---the return value of a function is an rvalue, and
the built-in unary & operator requires an lvalue.)
p.release(); // Would free up

No. This will release ownership of the pointer from the
auto_ptr, meaning that it is up to you to delete it. One
frequent use of auto_ptr is when creating objects with arbitrary
lifetimes which will later be managed by some special type (a
transation, for example), or by the object itself (which
registers somewhere for events). In such cases, it is usual to
create the object in an auto_ptr, and then call release when the
final management method has taken over, allowing auto_ptr to
manage the object until then.

It's the destructor of auto_ptr which deletes the object, but
only if you haven't called release.
return ( EXIT_SUCESS);
}
void func(T *output)
{
output->do_Something();
}
Now if there is any exception gets thrown in the func()
what would be the behaviour of auto_ptr ??

If the exception propagates beyond the scope of the auto_ptr,
it's destructor will be called, and the object will be deleted.
Also in a function call please correct me if I am wrong I can
use * as func(*(p.get())); correct ?

If the function takes a reference, yes, but it's very
unidiomatic. What's wrong with simply *p? (Unless the function
needs to be able to take a null pointer (e.g. for an optional
argument), I'd declare it to take a reference.)
James .. My another question is
for allocating a memory to an array of structures
You mentioned about using vector like below
int main ()
{
std::vector< T > obj( n + 1 ) ;
func(obj);
return(EXIT_SUCCESS);}
void func(&obj)
{
obj->do_Something();
}
if any exception is thrown in func() .. what will the end result ?

If the exception is not caught earlier, the destructor of
std::vector<T> will be called, which will call the destructor of
all of the elements in the vector, and free up any memory the
vector uses.
 
J

James Kanze

On Dec 7, 5:32 pm, Ami <[email protected]> wrote:
This is what I have now .. to overcome the flaw of passing by
value ...

What's the "flaw" of passing by value? If your types have value
semantics, it's usually what you want.
Now I have
int main ()
{
auto_ptr<T>p = (new T()) ;
func(p); // appending get() wont work in a function call
p.release();
return ( EXIT_SUCESS);
}
void func(const auto_ptr<T> &output)
{
output->do_Something();
}
works just fine..
Can you please let me know if this is the best way of passing
auto_ptr by reference and avoiding any leaks ?

In general, I don't like passing references to auto_ptr. Either
the called function is going to take over ownership, and passing
the auto_ptr by value would seem to be indicated, or it's not,
and either derferencing the auto_ptr to pass by reference, or
calling get to pass by pointer, would seem more appropriate.
also why get() doesnt work in a function call func(p.get()) //
throws error

What is the signature of func? If func takes a T* (or a T
const*), then p.get() should work.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,564
Members
45,040
Latest member
papereejit

Latest Threads

Top