"unsafety" is a very overloaded term. In this context, one specific technical meaning is assumed: _memory safety_ [0] (not type safety, not safety from hacking, etc, although they do depend on memory safety).
Programming languages are tools for building abstractions and concrete implementation of abstractions. They are very rarely verified and described mathematically and exhaustively; it is possible to state some properties of some programs, but it is mathematically impossible to state any meaningful property for an arbitrary program [1].
However, it is possible to constrain used abstractions in a way that allows to uphold some properties (to some degree). Memory safety of a language means that a program in that language can change a variable/state if and only if it "touches" it semantically (e.g. via a valid pointer/reference). A memory-safe language creates a reliable "abstraction cage" for (almost) any program written in it that guarantees (but not necessarily mathematically) that unrelated variables cannot be changed. "Glitches in the Matrix" (changing one variable magically changes a random other one) are still possible, but very rare in practice. Examples: Java/Python (which incur significant inefficiency when executing a program), and recently (the safe part of) Rust, which often comes very close to C/C++ in efficiency while retaining memory safety in most of its code.
C/C++ are examples of memory unsafe languages: their memory abstractions are not even close to an "abstraction cage"/"Matrix", they are just thin "guardrails" and guides, not enforceable rules: it is easy to read/corrupt an unrelated variable in a program (sometimes even via a malicious input to a program). This design choice was semi-deliberate: C/C++ solve the task of programming existing computer hardware efficiently and nobody knew how to create a practical, efficient and memory-safe systems programming language even twenty years ago. It is possible for a coder to code "defensively", using empirical best practices and tools for reducing possibility of using program memory incorrectly. C++ has a subset and tooling that comes tantalizingly close to memory safety, but it is still a costly uphill battle and even the best C/C++ coders/organizations fail to avoid memory misuse.
Programming languages are tools for building abstractions and concrete implementation of abstractions. They are very rarely verified and described mathematically and exhaustively; it is possible to state some properties of some programs, but it is mathematically impossible to state any meaningful property for an arbitrary program [1].
However, it is possible to constrain used abstractions in a way that allows to uphold some properties (to some degree). Memory safety of a language means that a program in that language can change a variable/state if and only if it "touches" it semantically (e.g. via a valid pointer/reference). A memory-safe language creates a reliable "abstraction cage" for (almost) any program written in it that guarantees (but not necessarily mathematically) that unrelated variables cannot be changed. "Glitches in the Matrix" (changing one variable magically changes a random other one) are still possible, but very rare in practice. Examples: Java/Python (which incur significant inefficiency when executing a program), and recently (the safe part of) Rust, which often comes very close to C/C++ in efficiency while retaining memory safety in most of its code.
C/C++ are examples of memory unsafe languages: their memory abstractions are not even close to an "abstraction cage"/"Matrix", they are just thin "guardrails" and guides, not enforceable rules: it is easy to read/corrupt an unrelated variable in a program (sometimes even via a malicious input to a program). This design choice was semi-deliberate: C/C++ solve the task of programming existing computer hardware efficiently and nobody knew how to create a practical, efficient and memory-safe systems programming language even twenty years ago. It is possible for a coder to code "defensively", using empirical best practices and tools for reducing possibility of using program memory incorrectly. C++ has a subset and tooling that comes tantalizingly close to memory safety, but it is still a costly uphill battle and even the best C/C++ coders/organizations fail to avoid memory misuse.
[0]: https://en.wikipedia.org/wiki/Memory_safety [1]: https://en.wikipedia.org/wiki/Rice%27s_theorem