The pragmatic approach is to use a toolchain which prevents data being executable. Most high level languages without pointers and direct memory access (excluding dynamic languages) perform this feat quite well.
I disclaim the use of hacks like non executable segments here in certain CPU architectures (x86 LDT/GDT controlled access bits) as they are an afterthought.