Application run into errors when accessing an unknown/undefined memory location (e.g., dereferencing via uninitialized or deleted pointers). Memory leaks occur when you lose track of a piece of dynamically allocated memory. The following are examples of typical pointer-related issues in C++, which I abbreviate as UNDO (UNinitialized, Deleted, and Overridden) Pointers.

Uninitialized pointer

    int *p; // p is an uninitialized pointer 
    *p = 3; // bad!

A NULL pointer is still uninitialized:

    int *p = NULL; //p is still uninitialized
    *p = 3; // bad! 

Deleted pointer

    int *p = new int;
    delete p;
    *p = 5; // bad!

Dangling pointer is a pointer to a location that had been pointed to by another pointer, which has been deleted. I consider dangling pointer a special case of deleted pointer.

    int *p, *q;
    p = new int;
    q = p; // p and q point to the same location
    delete q; // now p is a dangling pointer
    *p = 3; // bad!

Overridden pointers

A pointer p points to dynamically allocated memory, and you reassign (overwrite) p without first deleting it, that memory will be lost and your code will have a memory leak.

    int *p = new int;
    p = NULL; // pointer reassignment without freeing the memory

Reference

This post is my learning notes summarized from the tutorial Learning a New Programming Language: C++ for Java Programmers.