Okay fine... the premise of your problem is incorrect. You don't catch bugs. You catch C++ exceptions. If the bug is not an exception, you can't catch it. Things like buffer overflows and undefined behavior are still bugs, but not exceptions.
There are neat Microsoft-specific things like __try and __catch that let you handle a wider variety of "structured exceptions", but most likely you do not need this. Fix the actual bug instead.
You have hit a language design philosophy topic. C# is designed as if the programmer does not know what to do, and protects the child from himself by hiding all the sharp knives in a locked cabinet. C++ lets the kid juggle knives if he wants to, but sometimes he gets cut -- it is designed expecting the child (the coder) to do things properly but it does not force the issue.
C# certainly does not catch all the bugs. It mostly catches memory access violation errors, which c++ can do too (see vector.at) but the coder decides if they want the checks (slower and safer) or not (faster but risky).
C# is aggravating to use, they forgot to allow unsigned integers and many other simple things. It has become a very nice language for making a windows GUI; M$ has assaulted the C++ side of gui development harshly to promote their language and make it the more viable option, sort of a disgusting approach but all that aside, its not bad for windows gui programming niche.
everything can be decompiled. The confusion tools make it hard to follow what you get out of the decompiler, not that it cannot do it. Which to me raises a red flag that the scrambled code is probably not efficient at the assembly level, but you can always get the cpu instructions back out and if you are determined enough or have enough people you can go from there.