As you have surmised, your problem is fragmentation. There's nothing you can do to defragment memory--any tool that would attempt to do so would have to have a complete map of every pointer in your program. Note that even .NET's garbage collector can't accomplish this with the large object heap, I have crashed a 32-bit net application with only 100mb actually used.
Instead, what you need to do is avoid the fragmentation in the first place. Generally that means object pools, saving old objects for reuse rather than freeing them and later reallocating them.