Indeed.
The only way to be sure all possible leaks and dangling pointers are detected without running it is to do a complete static analysis of the program and any library functions or (exploit knowledge of) compiler built-ins the program uses, and verify that all possible program states are in valid ranges.
Whole-of-program static analysis is difficult - and the reason that programs which do comprehensive static analysis are often VERY expensive, are rarely used on small programs, and novices very rarely get to use them.
Even primitive forms of static analysis are quite time consuming, because of the number of dependencies of state that can arise between functions that call (or are called by) each other - and because a program that can accept inputs (from user, from files, from whatever) has many more possible states. There are ways and means of simplifying static analysis (for example, annotations of preconditions and post conditions of functions, so the analyser doesn't have to drill down and analyse the source of every called function) but it is hardly trivial.
Built-in reference-counted smart pointers can help, but they're hardly a panacea. They're also not the only available option - there is nothing stopping a compiler vendor building in knowledge of the standard library into a compiler (there are several compilers, for a range of languages including C and C++, which exploit knowledge of the standard library to improve diagnostics or to optimise performance).