Without a virtual destructor, the code;
Code:
BaseClass *x = new DerivedClass; // DerivedClass is derived from BaseClass
delete x; // undefined behaviour here
yields undefined behaviour. The existance of virtual member functions in the base class implies that there may be a derived class, and the above is a pretty common usage pattern in practice. Net result is that, if a class has any virtual member functions, it is usually a good idea for it to also have a virtual destructor.
Garbage cleanup is not automatic when you do dynamic memory allocation: it is necessary to explicitly (and correctly) release dynamically allocated objects.