Think of it in C/C++ terms.
Anytime you make a "new" something, or use malloc, that goes on the heap-- that is, the "object" goes on the heap, the pointer itself is placed on the stack within the scope of the structure (or function, which is really just another structure) that it's part of. If it's a local variable or reference type (pointer), it goes on the stack.
To put it another way, the >object< that the reference type is pointing to is on the heap, it's just the pointer itself that's on the stack. Memory leaks occur when the program pops the pointer off the stack, but the memory in the heap hasn't been freed for use-- how do you know what memory to free it if the reference to it's location has been lost? Well, C/C++ couldn't, you had to do it yourself before the reference was popped off the stack and lost forever, but that's where modern languages come in with their fancy shmancy "garbage collection heaps". It's still preferable to explicitly clean up any heap memory you allocated than implicitly by leaving it for the GC to pickup, it's "cheaper" that way (in terms of CPU resources).