It's not as if non-C approaches investigated at the same time are flawless.
Pascal-style strings prefixed with length are also problematic because the length has to be tracked by all operations to that string, so you can still cause buffer overflows by triggering a bug in that logic, and you need to pre-estimate the string size range to know whether a byte or word is appropriate for length, or use some variable integer type. And don't get me started about the hodge-podge that C++ strings are with SSO and reallocated/pooled buffers.
Use after free() can is a consequence of a lack of garbage collection and memory management built into the language. This was probably not a conscious decision, there was just no need for it when Unix systems typically had under a megabyte of memory. Besides, even if it was considered at the time, you couldn't just rely on your interpreter or language to handle memory for you, you had to do it properly, else you'll just run out.
The biggest issue I have with modern languages is the level of bloat they add to remove errors that could be avoided by conscious security design and audits. The reality is that security is only seemingly a concern when things go wrong, so these checks only get done on the most essential software. I mean, come on,
things like the printf() BMW bug are just showing embarrassingly poor practices that signal overall bad practice in the organisation, rather than a failure of the language itself.