A cursory look at the CVE list for any C software in the wild indicates that no, there are not simple ways to avoid shooting yourself in the feet with manual memory management in C. It's _incredibly hard_ even for "elite" programmers who have a lot of incentive to avoid these problems. The counterpoint is that people are probably going to spend less time looking for ways to maliciously use those problems in your C game than they are in the Linux kernel, but there is plenty of potential for even seasoned C coders to engage in bullet-on-foot violence.
Writing super secure code is usually not a requirement for gamedev, and I completely agree, this is hard and potentially harder in C than, say, in Rust.
I am far from an expert in security but I've done a bit of reversing/hacking when I was 16 years old (DOS era)
I think this is hard to check for everything, but in my opinion, good security can be achieved with extreme simplicity.
Packets are fixed-size, every fields are manually bound checked and the packet is rejected if anything looks wrong.
But I've seen some real weird stuff before. ;) Folks using variable-length fields and happily just dumping the contents into eval(), all sorts of awful.
The OS should protect where it can. So should software, lest your networked game nuke, say, the parts of your home directory to which it has permissions because without those permissions it can't do something it needs to.
This is just defense-in-depth. It's super basic stuff and HN is literally the only place I see people galaxy-braining about the idea that you have an obligation to not write shit code.
Defense in depth. Write good, sane, secure, fail-closed code when you want to ship that code to other people--or don't write code.
A first line of defence is authentication. Make sure the packets come from a trusted source (you can MAC each packet for this), so only those trusted sources could possibly trigger the vulnerability.
If the only trusted source is an authoritative server, you might be able to hide that buffer overflow. If your network code is peer to peer however, you have to trust the other players not to run a cheat that takes over your machine… but at least that's not the whole internet.
In fact, generally a memory safety vulnerability will initially manifest itself as a crash before a more advanced targeted exploit can be used against it.
Many consoles have been "jailbroken" by making buggy games load specially crafted savegames that ended up in code execution.
That also extends to players downloading innocent-looking maps, savegames, models. etc that exploit bugs and end up in code execution too.
Also if you have an online game then you can have RCE bugs, especially if players are expected to be able to connect to 3rd party servers.
(Not saying I necessarily disagree with you, just a counterpoint)
That's an argument for using C in gamedev, isn't it? ;)
How can I see that list? I'm interested in comparing languages this way.
If by OOP you mean virtual functions? Nobody uses that stuff much anymore, except Java refugees. (They use shared pointers, too.) But, anyplace you would use a function pointer in C, it's cleaner with a virtual function, and often faster.
Why? My understanding is that in modern game dev you're mostly traversing large arenas of structured memory, and you avoid freeing individual objects like the plague.
D3D11_MAPPED_SUBRESOURCE mapped;
context->Map( buffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
// Write memory address pointed by mapped.pData
context->Unmap( buffer, 0 );
With C++ RAII, you can do something like that instead: MappedBuffer mapped{ buffer }
// Write memory address pointed by mapped.pData.
// No need to do anything else, the destructor of MappedBuffer will unmap.Excuse my C/C++ ignorance, but why not simply use C?
So by definition require OOP?
But I guess there's no point in arguing over semantics.
[1] As Wikipedia defines OOP: "a programming paradigm based on the concept of "objects", which can contain data, in the form of fields (often known as attributes or properties), and code, in the form of procedures (often known as methods)." https://en.wikipedia.org/wiki/Object-oriented_programming
But nobody seriously uses virtual functions anymore, except where they would need to use function pointers, and for precisely those uses virtual functions are way better: cleaner, safer, often faster.
To avoid cache misses you can't use OOP, that's probably where this wave of going back to C is coming from:
For example here's how someone that knows how computers work writes Java games: http://www.javaonthebrain.com/java/warp/warp.java
https://gcc.gnu.org/onlinedocs/gcc/Common-Variable-Attribute...
C++ with structs and 99% procedural code is actually very close to vanilla C.
Let's not be pedantic here.
I liked Handmadehero for this reason, he is so arrogant and certain about how to properly write code, but when you actually see how he codes, what mess he produces and how long he spends live debugging it all the time. He constantly finds bugs in code he wrote earlier, etc. Yet he is so totally unable to find anything remotely wrong about the way he does things, and that there might have been some ideas invented in the last 30 years that could make him more productive.
I have zero respect for those types of programmers. I would quit any job instantly if I ever had to work with guys like this.
You understand that he is an extremely successful programmer in his field and has the respect of thousands of programmers world wide?
Maybe you can share some of your accomplishments with us.
A few examples: https://handmadehero.org/ https://ourmachinery.com/post/physical-design/
Simple libs widely used in game dev circles: https://github.com/nothings/stb
This one is a full game engine with tools made for educational purpose: https://www.raylib.com/
I do write games and game engine code and tools in C++ without using any of the OOP features.
I know quite a few of other professional, experienced and talented developers doing the same, even full AA studios with up to 50 employees.
Some of them are going back to procedural C after a few years of disappointment with OOP madness.
I'll publish articles about this later, but for now, all I have to say is that it just works.
Newbies are often afraid of manual memory management and pointers, but there are simple ways to avoid shooting yourself in the feet with those.