There is no way to be absolutely sure various kinds of undefined behavior (in particular race conditions) don't exist.
However, there are a number of tools that show up a good number of such situations. You may be able to prove that a problem exists currently with such tools, even though you cannot prove that your fix is valid.
Some interesting tools for this purpose:
Valgrind is a memory checker. It finds memory leaks, reads of uninitialized memory, uses of dangling pointers and out-of-bounds accesses.
Helgrind is a thread safety checker. It finds race conditions.
Both work by dynamic instrumentation, i.e. they take your program as-is and execute it in a virtualized environment. This makes them unintrusive, but slow.
UBSan is an undefined behavior checker. It finds various cases of C and C++ undefined behavior, such as integer overflows, out-of-range shifts and similar stuff.
MSan is a memory checker. It has similar goals as Valgrind.
TSan is a thread safety checker. It has similar goals as Helgrind.
These three are built into the Clang compiler and generate code at compile time. This means that you need to integrate them into your build process (in particular, you have to compile with Clang), which makes them much harder to initially set up than *grind, but on the other hand they have a much lower runtime overhead.
All the tools I listed work on Linux and some of them on MacOS. I don't think any work on Windows reliably yet.