Software isn't fault free.
When dealing with mission critical software, sure, you need to invest a lot more in quality assurance, and you need the best developers you can get, and you need to get them all the fancy tools and use them (including picking the best language for the job). With all that, you're still going to get bugs.
The main solution is basically a form of defense in depth.
Redundancy is a great thing. In widest sense, you want multiple independent systems that use multiple separate ways to get to the same answer. This way, if some path fails, you'll notice the error, and you will have a way to choose the correct answer, if you're lucky. This is used everywhere from the Shuttle to Nuclear power plants, and not just with software.
You also need to understand your failure modes. There might be a failure that doesn't have any long-reaching effects - that's a pretty mild failure. If there's a temporary issue that causes your program to crash "safely", restarting might be good enough. In many mission critical scenarios, this is perfectly fine, especially combined with redundancy above. If there's a possibility to corrupt saved state in a way that cannot be resolved with a restart, or if the same error can cause your system to fail repeatedly in a scale that doesn't fit the mission requirements, you're in way more trouble. The worst case of all is a silent failure - basically, something went wrong, but it didn't raise any alarms. This can cause long-term corruption of the data, and quite a bit of harm before being detected. Again, see redundancy above. There's a bit of overlap between the different failure modes - for example, a probe that did a longer burn than expected might be discovered as soon as we get the data back (light is slow), but by then it might have already been lost. Still, you want to know about failures, so silent failures are often very ugly.
Unsurprisingly, mission critical systems tend to be rather expensive for both development and deployment, and they have many additional constraints and usually a limited speed (for example, you may have three different algorithms cross-checking each other, but one of them is faster than others and so you could get a faster result by only checking that one). As always, engineering is about trade-offs.