You can also insert stack-protecting canaries with some compilers (-fstack-protector on GCC). A bit more limited and it incurs a small runtime cost but you only need compiler support.
Stack canaries make these attacks much more annoying, but it’s still possible to perform these if you can overwrite a function pointer or perform a controlled read or write (rather than a buffer overflow).