Detecting vulnerabilities in C code is hard science and still an open problem. The best known tool for that is still the human brain. This is called code review. This kind of things work is you take care to put the burden of proof on the developer.
Indeed, the common situation is that the developer produced the code, then the reviewer tries to make sense out of it. But the developer will not fix anything until the reviewer demonstrates a vulnerability. That's what occurs in a lot of software projects in which the "reviewers" are "the Internet at large", and the software vendor proposes a patch only when an actual exploit has been found and published. This is quite unsatisfying.
Instead, have the developer writes clear code with lots of comments, so that a reviewer with access to the source code can understand what the code does, and see why the buffers are obviously not overflown. Under these conditions can code review be efficient, mainly because it forces the developer to himself have a clear view of his own task.
Dynamic tools like Valgrind are great as debugging tools, but not so great at detecting potential vulnerabilities. They will tell you whether a buffer overflow has occurred during tests, not whether an overflow could have occurred with different input data.
C is a difficult language because you have to think of everything. One common source of buffer overflows in C is handling of character strings, because C does not have character strings worth that name, only array of characters with the convention of a terminating zero. Other programming languages will offer real strings which can be concatenated and split and shared as if they were mere integers; such strings avoid a lot of buffer overflows by simply being much simpler to use. Of couse, simple-to-use strings require some sort of automatic memory management, be it a garbage collector or reference counting (to some extent, C++ can do reference counting for strings, but you still need to convert back to arrays of chars when interacting with the operating system).
None of the above directly applies to your problem of detecting vulnerabilities in existing applications. It just shows that your task is hard. It can be proven that it is impossible in all generality (you may never automatically detect all vulnerabilities).