Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Memory deallocation does not work.

Reply
Thread Tools

Memory deallocation does not work.

 
 
christophe.chazeau@gmail.com
Guest
Posts: n/a
 
      02-12-2007
Hi,
I have a problem with a really simple chunk of code which should work
but does obviously does not.
This chunk of code is just a POC aimed at finding a bug in a larger
project in which the same problem seems to occur.
Here the deal : when I run this piece of code, I expect all the memory
allocated by the "Test" object to be freed but what I observe is that
after the second sleep (after all the additions to the vector), the
memory taken by the process is 750Meg which is normal but after the
last sleep, the memory occupied by the process stays as high as 590Meg
when I expected it to be freed completely.

What exactly is wrong with this code ??
Thanx a lot in advance


Code :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <vector>
#include <iterator>


using namespace std;


class Test{
public :
unsigned char *data ;

Test(){

}
void Go(int taille)
{

data = (unsigned char*) malloc(taille);
printf("malloc : %p\n",data);
}

~Test()
{
printf("delete %p\n",data);
free(data);
}

};

vector<Test *> v;
int i = 0 ;

int main()
{

sleep(10);

for(i = 0;i<10000;i++)
{
Test *t = new Test();
t->Go(75000);
v.push_back(t);
}

sleep(10);

vector<Test *>::iterator it;
for(it=v.begin() ; it!=v.end();it++)
{

Test *t = *it;
delete(t);
}
sleep(10);

}

 
Reply With Quote
 
 
 
 
Andre Kostur
Guest
Posts: n/a
 
      02-12-2007
http://www.velocityreviews.com/forums/(E-Mail Removed) wrote in news:1171302593.431343.309790
@q2g2000cwa.googlegroups.com:

> Hi,
> I have a problem with a really simple chunk of code which should work
> but does obviously does not.


No... it's not obvious that it does not "work".

> This chunk of code is just a POC aimed at finding a bug in a larger
> project in which the same problem seems to occur.
> Here the deal : when I run this piece of code, I expect all the memory
> allocated by the "Test" object to be freed but what I observe is that
> after the second sleep (after all the additions to the vector), the
> memory taken by the process is 750Meg which is normal but after the
> last sleep, the memory occupied by the process stays as high as 590Meg
> when I expected it to be freed completely.
>
> What exactly is wrong with this code ??
> Thanx a lot in advance


The assumption you have is that when you delete (or free) memory from your
program that it is necessarily handed back to the OS. That's
implementation-specific behaviour as to whether if and/or when that is
actually done.
 
Reply With Quote
 
 
 
 
red floyd
Guest
Posts: n/a
 
      02-12-2007
(E-Mail Removed) wrote:
> Hi,
> I have a problem with a really simple chunk of code which should work
> but does obviously does not.
> This chunk of code is just a POC aimed at finding a bug in a larger
> project in which the same problem seems to occur.
> Here the deal : when I run this piece of code, I expect all the memory
> allocated by the "Test" object to be freed but what I observe is that
> after the second sleep (after all the additions to the vector), the
> memory taken by the process is 750Meg which is normal but after the
> last sleep, the memory occupied by the process stays as high as 590Meg
> when I expected it to be freed completely.
>
> What exactly is wrong with this code ??
> Thanx a lot in advance


Other than the use of malloc/free instead of new[]/delete[]?

As far as I can tell, nothing. What is wrong is your expectation. free
and delete return the memory to the free store. Whether said memory is
returned to the operating system is completely system dependent.

So the memory is being deallocated in the sense that accessing memory
through the pointers is no undefined, as the memory is returned to the
free store, it's just not being returned to the OS.

If you need such behavior to occur, you will need to deal with OS
specifics. I suggest asking in a newsgroup dedicated to your platform.
You can find a partial list of such newsgroups at
http://www.parashift.com/c++-faq-lit...t.html#faq-5.9


 
Reply With Quote
 
christophe.chazeau@gmail.com
Guest
Posts: n/a
 
      02-12-2007
On 12 fév, 19:11, red floyd <(E-Mail Removed)> wrote:
> (E-Mail Removed) wrote:
> > Hi,
> > I have a problem with a really simple chunk of code which should work
> > but does obviously does not.
> > This chunk of code is just a POC aimed at finding a bug in a larger
> > project in which the same problem seems to occur.
> > Here the deal : when I run this piece of code, I expect all the memory
> > allocated by the "Test" object to be freed but what I observe is that
> > after the second sleep (after all the additions to the vector), the
> > memory taken by the process is 750Meg which is normal but after the
> > last sleep, the memory occupied by the process stays as high as 590Meg
> > when I expected it to be freed completely.

>
> > What exactly is wrong with this code ??
> > Thanx a lot in advance

>
> Other than the use of malloc/free instead of new[]/delete[]?


Yeah I know but we need to reallocate from time to time, so that's the
reason why we chose malloc/free
Do you know a better way of dealing with variable size buffer in C++
objects ?


> As far as I can tell, nothing. What is wrong is your expectation. free
> and delete return the memory to the free store. Whether said memory is
> returned to the operating system is completely system dependent.
>
> So the memory is being deallocated in the sense that accessing memory
> through the pointers is no undefined, as the memory is returned to the
> free store, it's just not being returned to the OS.
>
> If you need such behavior to occur, you will need to deal with OS
> specifics. I suggest asking in a newsgroup dedicated to your platform.
> You can find a partial list of such newsgroups athttp://www.parashift.com/c++-faq-lite/how-to-post.html#faq-5.9


Thanx a lot for the answer : that's what I wanted to hear : the memory
is freed but not yet returned to the OS.
Would it eventually be returned after a certain amount of time ? That
is to say if the last sleep is long enough, would the used virtual
memory decrease in a top (Yeah I forgot to mention all this is
intended to run under Linux)

Anyway Thank you to you and Andre.

Christophe

 
Reply With Quote
 
red floyd
Guest
Posts: n/a
 
      02-12-2007
(E-Mail Removed) wrote:
> On 12 fév, 19:11, red floyd <(E-Mail Removed)> wrote:


>> Other than the use of malloc/free instead of new[]/delete[]?

>
> Yeah I know but we need to reallocate from time to time, so that's the
> reason why we chose malloc/free
> Do you know a better way of dealing with variable size buffer in C++
> objects ?
>
>

std::vector
 
Reply With Quote
 
Grizlyk
Guest
Posts: n/a
 
      02-12-2007

(E-Mail Removed) wrote:
>
> #include <stdio.h>
> #include <stdlib.h>
> #include <unistd.h>
> #include <vector>
> #include <iterator>
>
>
> using namespace std;
>
> class Test{
> public :
> unsigned char *data ;
>
> Test(){
>
> }
> void Go(int taille)
> {
>
> data = (unsigned char*) malloc(taille);
> printf("malloc : %p\n",data);
> }
>
> ~Test()
> {
> printf("delete %p\n",data);
> free(data);
> }
>
> };
>
> vector<Test *> v;


It is dangerous - possible memory leak because vector<Test *> does not own
the object pointer point to. Use any RAII memory wrapper (see RAII here:
http://www.hackcraft.net/raii ) instead of Test *

vector<auto_ptr<Test> > v;

or give each address (stored in vector<Test *>) to other object, which will
keep object.

{
auto_ptr<Test> owner(new Test);
vector<Test *> v;
v.push_back(*owner);
}

> int i = 0 ;
>
> int main()
> {
>
> sleep(10);
>
> for(i = 0;i<10000;i++)
> {
> Test *t = new Test();
> t->Go(75000);
> v.push_back(t);
> }
>
> sleep(10);
>
> vector<Test *>::iterator it;
> for(it=v.begin() ; it!=v.end();it++)


Do you need "it" outside of "for"?
Try to inplement postfix operator ++, and you will see, that pferix ++ is
better.
Avoid repeating function call "v.end()" if you are sure, that the function
will always return the same.

> vector<Test *>::iterator end(v.end());
> for(vector<Test *>::iterator it(v.begin()); it!=end; ++it)


> {
>
> Test *t = *it;
> delete(t);
> }
> sleep(10);
>
> }


To return memory to OS, instead of std malloc/free you need to implement
native for you OS memory manager

namespace Nxxx_OS
{
void* malloc(); //will call OS specific allocate
void free(void*const); //will call OS specific free

//namespace Nxxx_OS
}

Note, you need to stay coherrent with all other memory management, so
probably you need to change all system memory allocation for the target.

--
Maksim A. Polyanin

"In thi world of fairy tales rolls are liked olso"
/Gnume/


 
Reply With Quote
 
Andre Kostur
Guest
Posts: n/a
 
      02-12-2007
"Grizlyk" <(E-Mail Removed)> wrote in news:eqqrpd$or9$(E-Mail Removed):

>
> (E-Mail Removed) wrote:
>>
>> #include <stdio.h>
>> #include <stdlib.h>
>> #include <unistd.h>
>> #include <vector>
>> #include <iterator>
>>
>>
>> using namespace std;
>>
>> class Test{
>> public :
>> unsigned char *data ;
>>
>> Test(){
>>
>> }
>> void Go(int taille)
>> {
>>
>> data = (unsigned char*) malloc(taille);
>> printf("malloc : %p\n",data);
>> }
>>
>> ~Test()
>> {
>> printf("delete %p\n",data);
>> free(data);
>> }
>>
>> };
>>
>> vector<Test *> v;

>
> It is dangerous - possible memory leak because vector<Test *> does not
> own the object pointer point to. Use any RAII memory wrapper (see RAII
> here: http://www.hackcraft.net/raii ) instead of Test *


Uh... not all RAII memory wrappers are usable for this purpose.

>
> vector<auto_ptr<Test> > v;


Specifically auto_ptr is not!

>
> or give each address (stored in vector<Test *>) to other object,
> which will keep object.
>
> {
> auto_ptr<Test> owner(new Test);
> vector<Test *> v;
> v.push_back(*owner);
> }


Only if you know these other objects are going to have a longer lifetime
than your vector...

 
Reply With Quote
 
Kai-Uwe Bux
Guest
Posts: n/a
 
      02-12-2007
Grizlyk wrote:

>
> (E-Mail Removed) wrote:
>>
>> #include <stdio.h>
>> #include <stdlib.h>
>> #include <unistd.h>
>> #include <vector>
>> #include <iterator>
>>
>>
>> using namespace std;
>>
>> class Test{
>> public :
>> unsigned char *data ;
>>
>> Test(){
>>
>> }
>> void Go(int taille)
>> {
>>
>> data = (unsigned char*) malloc(taille);
>> printf("malloc : %p\n",data);
>> }
>>
>> ~Test()
>> {
>> printf("delete %p\n",data);
>> free(data);
>> }
>>
>> };
>>
>> vector<Test *> v;

>
> It is dangerous - possible memory leak because vector<Test *> does not own
> the object pointer point to. Use any RAII memory wrapper (see RAII here:
> http://www.hackcraft.net/raii ) instead of Test *
>
> vector<auto_ptr<Test> > v;


That is _bad_ and much more dangerous than vector<Test*>: auto_ptr<> does
not satisfy the requirements for use in a container. Formally, you have
undefined behavior. In practice, you may run into trouble as soon as vector
reallocates.


> or give each address (stored in vector<Test *>) to other object, which
> will keep object.
>
> {
> auto_ptr<Test> owner(new Test);
> vector<Test *> v;
> v.push_back(*owner);


*owner is a Test& not a Test*. Do you mean

v.push_back( owner.operator->() );

> }


What happens at this "}"? The auto_ptr<Test> owner destroys the pointee. The
pointer stored in v now is invalid. Any further use is undefined behavior.

What exactly are you trying to to? Should you be headed for automatic memory
management, consider vector< shared_ptr<Test> > or a special container for
pointers that implements some ownership model.


>
>> int i = 0 ;
>>
>> int main()
>> {
>>
>> sleep(10);
>>
>> for(i = 0;i<10000;i++)
>> {
>> Test *t = new Test();
>> t->Go(75000);
>> v.push_back(t);
>> }
>>
>> sleep(10);
>>
>> vector<Test *>::iterator it;
>> for(it=v.begin() ; it!=v.end();it++)

>
> Do you need "it" outside of "for"?


That is a good point.

> Try to inplement postfix operator ++, and you will see, that pferix ++ is
> better.


"better" in which way?

Should you think of performance, your advice amounts to premature
optimization: chances are that it++ is inlined and optimized to the same
code that ++it would generate.

> Avoid repeating function call "v.end()" if you are sure, that the function
> will always return the same.


Very likely, this is also premature optimization.

[snip]


Best

Kai-Uwe Bux
 
Reply With Quote
 
Grizlyk
Guest
Posts: n/a
 
      02-13-2007

Kai-Uwe Bux wrote:
>>
>> It is dangerous - possible memory leak because vector<Test *> does not
>> own
>> the object pointer point to. Use any RAII memory wrapper (see RAII here:
>> http://www.hackcraft.net/raii ) instead of Test *
>>
>> vector<auto_ptr<Test> > v;

>
> That is _bad_ and much more dangerous than vector<Test*>: auto_ptr<> does
> not satisfy the requirements for use in a container. Formally, you have
> undefined behavior. In practice, you may run into trouble as soon as
> vector
> reallocates.


I have assumed you have write you own::auto_ptr<> with the same behaviour.
You can garantee at least runtime error is not sure, that std::vector<> does
usage of its data sequentally. The auto_ptr idiom (auto_ptr must move data
on copy) is so useful, that you can even replace std::vector<> by
own::vector<> if std::vector<> do not support auto_ptr idiom.

Anyway auto_ptr<Test> is just example of RAII wrapper.

>> or give each address (stored in vector<Test *>) to other object, which
>> will keep object.
>>
>> {
>> auto_ptr<Test> owner(new Test);
>> vector<Test *> v;
>> v.push_back(*owner);

>
> *owner is a Test& not a Test*. Do you mean
> v.push_back( owner.operator->() );


Take address, i have meant address of Test for "vector<Test *>"
v.push_back(&*owner);

>
>> }

>
> What happens at this "}"? The auto_ptr<Test> owner destroys the pointee.
> The
> pointer stored in v now is invalid. Any further use is undefined behavior.


At the point "v" is also destroyed. Lifetime of "owner" evidently must be
more than lifetime of "user" ("v").

> What exactly are you trying to to? Should you be headed for automatic
> memory
> management, consider vector< shared_ptr<Test> > or a special container for
> pointers that implements some ownership model.


The "shared_ptr<Test>" is very, very, very rare used. I even can not
remember when I used it last time, of course, if you have no suitable
auto_ptr, you must use any other wapper, for example "shared_ptr<Test>".

>
>> Try to inplement postfix operator ++, and you will see, that pferix ++ is
>> better.

>
> "better" in which way?


In all ways. Operation "*p++=0;" has perfomans sence only if it is single
opcode for POD.
For POD also builtin increment p++ and ++p can subst each other and compiler
can generate "*p=0, ++p;" automatically if needed.
For non POD both increments p++ and ++p are implemened by different user
functions, so for non POD just write "*p=0, ++p;".

> Should you think of performance, your advice amounts to premature
> optimization: chances are that it++ is inlined and optimized to the same
> code that ++it would generate.


Maybe, but not required by C++. When you say "it++", you tell to compiler,
that you want a copy of "it" returned after operations, else you change
semantic of post-increment. And process of creation of copy can be hard to
eliminate. Anyway, you must not create copies if you no need it and you must
not assume, that creation of copy can be eliminated if you not use result.

>> Avoid repeating function call "v.end()" if you are sure, that the
>> function
>> will always return the same.

>
> Very likely, this is also premature optimization.


I do not know is "premature" bad or good, but you must not call function
many times, if you want only one value returned. You must not assume, that
unknown function do nothing.

--
Maksim A. Polyanin

"In thi world of fairy tales rolls are liked olso"
/Gnume/


 
Reply With Quote
 
Grizlyk
Guest
Posts: n/a
 
      02-13-2007

Andre Kostur wrote:
>>>
>>> vector<Test *> v;

>>
>> It is dangerous - possible memory leak because vector<Test *> does not
>> own the object pointer point to. Use any RAII memory wrapper (see RAII
>> here: http://www.hackcraft.net/raii ) instead of Test *

>
> Uh... not all RAII memory wrappers are usable for this purpose.


Yes, all depends from usage.

>> vector<auto_ptr<Test> > v;

>
> Specifically auto_ptr is not!


Maybe std::auto_ptr can not, but auto_ptr is idiom, make own auto_ptr if you
want. Anyway, auto_ptr is just example of RAII wrapper.

> Only if you know these other objects are going to have a longer lifetime
> than your vector...


Yes.

--
Maksim A. Polyanin

"In thi world of fairy tales rolls are liked olso"
/Gnume/


 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
memory allocation deallocation ... pasa_1 C++ 19 11-02-2006 07:56 PM
std.textio, readline and memory deallocation Nicolas Matringe VHDL 9 09-04-2006 12:15 PM
memory allocation/deallocation question BigBrian C++ 12 04-07-2005 12:32 AM
Stack Memory Deallocation Problem yccheok@gmail.com C++ 2 12-18-2004 02:35 PM
Automatic memory deallocation by std::string ?? qazmlp C++ 1 03-07-2004 02:00 PM



Advertisments