Sounds a fair bit like the code base I work on. We have in the neighborhood of 5 million lines of (mostly C++) video game middleware that my department works on, all of which must be backwards compatible, all of which can't be significantly overhauled easily. It also builds on 15 different target platforms with 2-5 configuration variations per platform.
Similarly, we use Perforce. Similarly we have a CI system that builds our code on a farm of VMs, though ours does fairly extensive unit testing on every build. We also have a significant number of version permutations we test on a fairly regular basis as well.
We regularly, automatically, run Valgrind and it's on my to-do list to hook up the Microsoft static analyzer and investigate code coverage tools.
One saving grace is that the code base is very modular and has decently quick iteration times in general. Sometimes the legacy and the degree of cross-platform support can be frustrating but for the most part the infrastructure works so well now that it's no big deal.
- doesn't have the luxury of having code that's not backwards compatible,
- code that can't be thrown out every 3 years
- code that has been around for more than 5 years and isn't going away