views:

105

answers:

6

Additional thanks extend to Daniel Newby for answering my memory usage question (and Martin York for explaining it a bit more). It is definitely the answer I was looking for, but more of my other questions were answered by others.

Thanks everyone

for clearing up all of my concerns. Very pleased to see things running how I expect them to run.

I've run into something that I'm not exactly sure about.

In my program, I'm not using malloc()or free(). I'm making instances of my classes with new and I've made sure each one runs it's destructor when it's delete'd, however, there are no free() calls or even setting their pointers (to things inside a global scope, or other classes) to NULL or 0.

What I mean by "I've made sure", is not that I call each destructor. I only use delete to call on the destructor to run, but I have variables that increase by 1 everytime an object is created, and everytime it's destructor is run. This is how I've made sure the amount of objects I created are equal to the amount of destructors called.

Should I be using malloc() and free() anyway? Should I be NULLing pointers to things that I still want to exist?

A second question is why, when I look at my task manager, does my process never "drop" memory? It used to never stop gaining, and then I started deleting everything properly. Or so I thought.

Wouldn't free() or delete make the memory usage go down?

What practices should I pursue about malloc'ing and free'ing memory with linked lists?

+2  A: 

you should be using delete with a new and free with a malloc. delete will call the class' destructor so you don't have to explicitly call it. The purpose of the destructor is to release and resources the class might have and delete will free the memory as well.

The only time you should explicetly use the destructor is when you have initialized your object through placement new. You should put yourself in a position where the compiler generated code releases your resources -- read this article on the C++ idiom : resource acquisition is initialization.

Also setting the pointer of a class to null does nothing, there is no garbage collector in the background cleaning up your memory. If you don't free dynamic memory in C++ it will be "leaked" memory -- i.e., there are no links to the memory and it will never be reclaimed till the process exits.

p.s., once again do not mix the pairs of the memory allocation functions.

edt: don't implement linked lists, use the containers provided by the Standard template library. If you feel you need better performance use the intrusive containers from boost.

Hassan Syed
I'll make sure that I use one or the other from now on. Thank you.
noobjam
+2  A: 

There's rarely a reason to use malloc() and free() in a C++ program. Stick with new and delete. Note that unlike languages with garbage collection, setting a pointer to NULL or 0 in C++ has nothing to do with deallocating the memory.

Fred Larson
I have had a hard time getting away from the habit of using malloc and free for non class data.
rerun
You should try to get out of the habit. And if you're using malloc and free for dynamic array creation, please use vector instead.
Liz Albin
rerun: Remember structs are classes.
jmucchiello
A: 

You should use new and delete in preference to malloc()/calloc()/realloc() and free().

If you're creating linked lists you should use std::list. Also, look into std::vector

As far as the apparent memory usage of your application: it's quite likely that memory is not returned to the system until the application exits.

Liz Albin
A: 
  1. new and delete can more or less to be considered the C++ versions of malloc and free. So stick within one pair or another, i.e. if a pointer was created with new, it should be released with delete, which ensures the destructor call you mentioned. The malloc/free pair are not C++ aware, and just allocate and release a block of memory with no attached constructor/destructor semantics.

  2. Yes indeed I consider it good form to set pointers to NULL or zero when they've been freed or deleted. During debugging I also sometimes set them to something characteristic like 0xdeadbeef so they stand out.

  3. It's likely that the OS "memory usage" is reflecting the entire size of your process' heap, rather than your memory manager's idea of how much memory is allocated. When the allocator discovers that it doesn't have enough heap space, it grows the heap, and this will be reflected in the "memory usage" you're looking at. In theory it would be possible to shrink the heap accordingly on memory release, but this doesn't always happen. Thus you may only see the memory usage grow, and never shrink.

Michael Daum
Thanks for explaining why my memory usage doesn't decrease in size. I'll see if I can figure out how to make it do so.
noobjam
A: 

"Should I be using malloc() and free() anyway?"

No, in most cases. Stick with one form of memory management only. Trying to use both means that you will inevitably screw up and delete a malloc()ed item, or free() a newed item, giving a subtle bug. Stick with one form and you fix these bugs in advance.

"Wouldn't free() or delete make the memory usage go down?"

The OS allocates memory in pages, often 4 kiB in size. As long as a single byte of the page is still in use, it will not be returned to the OS. You are probably allocating many small items, but not deallocating all of them. (There are ways to help with a custom new/delete, but they are generally not worth the effort.)

Daniel Newby
Thank you. A bit of testing and this is absolutely the answer I was looking for. I would upvote if I could.
noobjam
A: 

In my program, I'm not using malloc()or free(). I'm making instances of my classes with new and I've made sure each one runs it's destructor when it's delete'd,

That is scary. You should not need to make anything run its destructor. It is allocated (new) it is destroyed (delete) the constructor is run atomatically on new and the destructor is run automatically on delete.

however, there are no free() calls or even setting their pointers (to things inside a global scope, or other classes) to NULL or 0.

There is no need to use malloc/free in C++ code (there are a few situations where you are using C libs that require malloced memory but they are explicitly documented and few).

Technically there is no need to set a pointer to NULL after you delete it.
It is good technique for a variable to go out of scope just after it is deleted so it can not accidently be re-used. If for some reason the pointer variable lives (ie does not go out of scope) for a long time after you call delete then it is usefull to set it to NULL so that it is no accidently re-used.

Should I be using malloc() and free() anyway? Should I be NULLing pointers to things that I still want to exist?

No and No.
Note: C++ unlike Java does not keep track of how many pointers point at an object.
If you have more than one pointer pointing at an object you need to use smart pointers (you should be using smart pointers anyway).

A second question is why, when I look at my task manager, does my process never "drop" memory? It used to never stop gaining, and then I started deleting everything properly. Or so I thought.

The application never releases back to the OS (on most OS's in normal situations).
So the memory will never go down (until the application exits).
Internally the memory management tracks all the frees so that the memory can be re-used. But if it runs out it will ask the OS for more and thus in the task manager the memory allocation will go up (this will not be returned to the OS).

Wouldn't free() or delete make the memory usage go down?

No.

What practices should I pursue about malloc'ing and free'ing memory with linked lists?

You should use Smart Pointers so you don't need to worry about when to delete an object.
They also make your code exception safe.

But if you using pointers. call delete to remove an element then set is value to NULL (the pointer scope is alive long after the delete is called).

Note: A boost:shared_pointer is very similar to a Java pointer. It tracks the number of pointers and deletes the object when the last reference to the object is destroyed. No need for you to do any deleting (just like Java) and all you actually need to do is call new (just like Java).

Martin York