#C++ #programming #memorysafety #coding #development
C++ beginner (not a developer, just someone who codes for fun) 👨💻
## The Dangers of C/C++ Programming 🚨
As a budding C++ enthusiast, you may have come across warnings about the “dangerous” nature of C/C++ programming. But what exactly makes these languages precarious, and how can you navigate the pitfalls? Let’s delve into the world of C/C++, uncovering the potential risks, and equipping you with the knowledge to code safely and efficiently.
### Understanding the Issue 🤔
The US government’s recommendation to use memory-safe languages like Rust and C# highlights a crucial concern in the software development community. While utilizing new/alloc and delete/free can help manage memory in C/C++, these languages still pose inherent risks due to their low-level nature.
#### The Perils of C/C++ Programming 💀
1. **Memory Leaks**: Forgetting to deallocate memory properly can result in memory leaks, causing your program to consume excessive memory and potentially crash.
2. **Buffer Overflows**: C/C++ lacks built-in safeguards against buffer overflows, leaving your program vulnerable to security breaches and unexpected behavior.
3. **Dangling Pointers**: Improperly managed pointers can lead to dangling pointers, resulting in undefined behavior and potential crashes.
### Solutions for Secure Coding ✅
To mitigate the risks associated with C/C++ programming, consider implementing the following best practices:
#### 1. Use Smart Pointers 🧠
Utilize smart pointers like `std::unique_ptr` and `std::shared_ptr` to automate memory management and prevent memory leaks.
#### 2. Avoid Raw Pointers 🚫
Minimize the use of raw pointers and prefer safer alternatives like references or smart pointers to reduce the likelihood of pointer-related issues.
#### 3. Bounds Checking 🛑
Implement bounds checking mechanisms such as `std::vector` or `std::array` to prevent buffer overflows and enhance the security of your code.
### Conclusion 🌟
While C/C++ programming may pose challenges in terms of memory safety, adopting proactive strategies and best practices can help you code with confidence and efficiency. By staying informed about the potential pitfalls and embracing secure coding principles, you can navigate the intricacies of C/C++ programming effectively.
So, fear not the “danger” of C/C++ – equip yourself with the right tools and knowledge to conquer any coding challenge that comes your way! 💪🚀
Sometimes people make mistakes. Sometimes they don’t allocate enough memory, and someone manages to enter a string that goes beyond the memory buffer and starts corrupting other data…
>If I use new/alloc and delete/free on everything I create I create on the heap there should be no problems right?
It’s easy to say when you’re writing toy programs of a few hundred lines. Once you get into huge sprawling programs built by teams of 20 with all sorts of branching and edge cases, not so much. Also memory allocation isn’t the only kind of danger out there.
C and C++ are very different languages, with the latter having actual memory safe features not available in the former. However, these are opt-in, so the potential for programmer error is still there.
It’s actually since C and C++ gives you way to much freedom. Infact, it allows you to do nearly everything to the computer. As a beginner, you most likely won’t come across too many issues though.
You will most likely come across a few of those issues once and if you start learning the win32 api however.
> From what I know, if I use new/alloc and delete/free on everything I create I create on the heap there should be no problems right?
Rust enforces correct memory management at compile time. C and C++ don’t. They will happily let you make a program which has double free, use after free, null dereferencing, and any number of other memory problems. In any somewhat complex software those problems happen inevitably.
Plus it also offers compile time guarantees for concurrency, which is even harder to get right.
> From what I know, if I use new/alloc and delete/free on everything I create I create on the heap there should be no problems right?
Just like we have no car accidents if people don’t drive into things.
So why does not all driver just decide to not drive into things?
Programmers attempt to make good software but it is natural to make mistakes. Even if you have plenty of tests you can make mistakes which are not noticed. This is the point of using safe programming languages, when you have built in safety meassures, the risk of some mistakes are much lower. When there are no safety meassures, more mistakes happen.
>why are C/C++ “dangerous”
Because it’s easy to do the wrong thing, and hard to do the right thing. “Correct” C++ require more code than incorrect one.
>From what I know, if I use new/alloc and delete/free on everything I create I create on the heap there should be no problems right?
Yes, but how sure you are that you will never, ever, forget the delete, or will always delete the thing that you actually want to delete? You will make mistakes. Don’t think that you’re superhuman.
And it’s easy to do mistakes.
C++ does have some facilities to remove the need to manually track what you did (smart pointers, scopes, destructors), but even with them, there are tons of caveats that a newbie will stumble on.
More modern languages are going from opposite direction: it’s easy to write safe code, but it’s hard to make mistakes.
Ultimately it comes down to injection and hijacking of stack leading to exploits.
You can end up smashing your monitor because you get angry by all those squiggles when you try to compile a piece of code.
> From what I know, if I use new/alloc and delete/free on everything I create I create on the heap there should be no problems right?
For any large codebase, windows, linux, android, chrome, etc. 70% of security errors ends up being related to not correctly handling memory like this. These are/should be the most well tested scrutinized codebases, which means that its statistically impossible to not make this mistakes given enough code.
Nothing is dangerous. You just have to equally use malloc() and free() functions.
What’s hard about that?
Programmers who used to live only in high abstractions domain perpetuate this myth.
They are probably imagining things in speculative space and the echo chamber grows.
Don’t do this condom programming where you use 999 abstractions for your own protection.
> From what I know, if I use new/alloc and delete/free on everything I create I create on the heap there should be no problems right?
‘skill issue’ has never been a valid response to people getting things wrong in software, the chrome team has loads of talented devs on it with a tonne of code review on an incredibly widespread & important project & even still 70% of their bugs are memory access related. relying on humans to always do things perfectly correct has never been a reasonable solution because that’s what we’re trying to do anyways
use after free & out of bounds memory access (such as reading element 11 of a 10 length array) can and will lead to undefined behaviour where anything can happen. this could be silent errors, crashes or allow for remote code execution
Tbh.. This sounds like a bunch of bs!!!
“Aviation in and of itself is not terribly dangerous. However it is, to an even greater extent than the sea, terribly unforgiving of any carelessness, incapacity, or neglect.”
My dad had that in a picture frame with a plane stuck in a tree. I feel that quote is good here to apply to memory unsafe languages.
C/C++ SHOULD be learned in my book. But they also just give you full access to everything on the computer. You can read and write to almost any memory location and if you don’t write the code to disallow, users may be able to as well. Hell, smart people can sometimes do it despite your best efforts. You can cause other people a LOT of damage if you don’t know what you’re doing.
You can very easily override data in memory locations used by other software or the system and as a result corrupt the data of other software or the system. You can also collect garbage from memory left by other software in memory which corrupt the data in your software.
For this obvious reason, viruses and malwares also commonly written in C/C++ which attempt to corrupt the system and data on purpose.
I can totally understand if governments no longer want to take the risk and prefer or even demand government software to be written in memory managed languages which provide more security.
Imagine ur working on code for something that might kill people, now imagine how you could write that code poorly in c++.
Pointers, Like a shotgun and you’re not a hunter and you don’t know WTF Stay inside.
that was the most asinine thing i’ve seen the government announce about technology in a long time. c/c++ isn’t dangerous, it’s just more prone to specific kinds of errors in the wrong hands. insecure software exists in all languages. be a dev for a while and have management down your neck about every cme that comes along as though they’re all equally meaningful and you’ll see how many real vulnerabilities there are. and there really are a lot, all over, in all languages, as well as a bunch of wasted time for stopping everything to address low risk issues.
A lot of C functions will allocate memory and the function header will indicate “caller is responsible for freeing X”
I’ve seen that cause a lot of issues.
It’s really just human error. With AI now I think we might be able to cut down on that stuff a bit.
The main one is that mommy JVM isn’t there to clean up after your mistakes. It’s dangerous not because it’s difficult, but because it’s easy to forget things.
I have next to no knowledge of C.
Forgetting to free up things in memory resulting in runaway processes over-time as it’s used is an inconvenience for customers who use your software.
>if I use new/alloc and delete/free on everything I create I create on the heap there should be no problems right?
That’s the big if.
It’s dangerous because the possibility that you forget exists. And by you, I mean the programmer you work with.
that’s not the only problem with c, it is very easy to index into memory you shouldn’t as well with a simple length check mistake. you as the programmer have to reason through things that other languages just do for you
In c you can walk off the array into other parts of the memory allocated to the program. You can write code that self alters during run time actually changing the set of instructions. It’s really neat.
Function pointers, void* casts, memcpy, non terminated char* strings…
There’s a ton of things in C++ that can lead to security holes to watch out for.
Using STL containers will solve a huge number of them as well as being establishing clear memory ownership rules (copying rather than sharing pointers.)
But you always have to be on your toes. But since your coding is for fun, it’s not a huge security vulnerability unless a lot of people use it.
I don’t think they are. But I can see.
Nothing dangerous. You get some really good programming practise habits in at the cost of handling some really stupid errors. If you dont dive too deep in and just learn and move on, youl be fine
Memory leaks aren’t the problem. The problem is when your code is somehow convinced to read from or write to a region of memory that it is not supposed to, or when a value changes when you aren’t expecting it to. Even with smart pointers and locks enabled by destructors, C++ is still prone to the aforementioned errors, because due to the way it’s currently designed, nothing stops a function that is passed a mutable value from mutating it thus violating any assumptions that you might have about its value. or a concurrent access from another thread from modifying a value that you are in the middle of reading. With languages like C++ and especially C, you are supposed to code very defensively in order to avoid these pitfalls, whereas in Rust the compiler ensures that safe code that compiles is memory safe. Obviously that, in order to allow the same level of flexibility as C and C++, Rust also lets you write unsafe code, but since safe Rust is fine for most situations, the amount of code that can have memory related problems is significantly reduced. Another great thing about Rust is that all of its abstractions have no run-time cost, so by design the performance should theoretically be on par and sometimes even surpass that of C and C++.
There ia a bit of a division in programming at the moment between developers who work on purely web technology who are characterized as not liking C/C++ because they heard or have experienced security issues introduced by those languages.
The other segment of programmers has to interface with hardware. These are technologies running real time systems where peoples lives may be on the line such as power plants, hydro electric dams, airplanes, ships, ect. These devices can be programmed with languages like Python, but often libraries may not be available, or more probably the people teaching you the job aren’t familiar with Python or whatever and so you get trained on C/C++ because 1) the white house isn’t paying for people to migrate legacy code and retrain programmers so businesses aren’t going to do it, and 2) if its not (known) to be broken re-writing it will certain introduce that possibility. Remember just because your code is now memiry safe doesn’t mean its correct or that you haven’t introduce security risks at higher levels.
Is it dangerous? It depends on what you are doing. If you are securing a Netflix account probably not. If you are controlling the flood gates on a hydro electic dam, yeah its dangerous. Its not that one can’t do what the other does, or that one is safer. Its that one is used for dangerous stuff due to the ingrained community of professionals that collectively work on those things.
Its hard to explain how different the two worlds are. One is hosted in a cloud and supports software that is 5-10 years old. Software running critical infrastructure can be 50 years old (no joke). It may interface with hardware controllers that are as old as 75-100 years old. These devices could be turbines the size of houses, they aren’t going to be replaced because the software doesn’t support them, someone is getting paid to keep that driver for that device updated. Maybe the controller gets replaced and the device gets fitted with new telemetry sensors and now someone has to custom code what to do with that telemetry. When does it alarm. When does it automatically flip relays for safety or optimization?
These things all interface with software that is almost entirely absent from Google. If you want to figure out a problem with this stuff Google is a very limited tool. Its best to understand the problem and the requirements, read the manual, read the code, and go from there. Google searching will probably only confirm the existence of the software, but everything else is trade secrets.
That’s my treatise on the subject.
C++ doesn’t have a built-in memory manager like Java. It is often referred to as garbage collection. This means it is up to the programmer to manage their memory. This leads to oversights and vulnerabilities in the code that are not easily spotted. This is the perfect breeding ground for nefarious hackers.
>From what I know, if I use new/alloc and delete/free on everything I create I create on the heap there should be no problems right?
The issue is, that in C and C++, there is nothing preventing you from keeping a pointer to something that was freed/deleted and accessing that pointer. Congrats, now you are accessing memory that does not contain the data you expected there to be, and may or may not contain some other data that you shouldn’t even be able to access via that pointer. That is the dangerous part – the data might be sensitive (think passwords) or safety relevant (think, target positions for steering mechanisms).
Similar problem occurs in C and C++ when you index into arrays/pointers. By default, there is nothing preventing you from indexing out of bounds and reading/writing memory that should not be accessible through that pointer.
If you look at any safety guidelines for C or C++ programming, these are the main issues being addressed in them – don’t manage memory manually unless you have to, don’t index into things without doing bound checks first, make sure your pointers don’t outlive the objects they are pointing to.
Modern C++ is somewhat better in this, in that it has build in mechanisms to do all these things automatically. Unfortunately, they are not the obvious default ways of doing stuff, because modern C++ is backwards compatible with old C++ (and to some extend, C), where the “dangerous” operations were the default.
> From what I know, if I use new/alloc and delete/free on everything I create I create on the heap there should be no problems right?
100% Wrong. There are so many esoteric mistakes you can make (ESPECIALLY in C). Skilled C/C++ programmers of course know most of the tricks and use tools to guard against these mistakes, modern C++ offers a bunch of language features that help massively, but at the end of the day developers will always make mistakes.
These mistakes can result in huge gaping security holes where applications can be completely taken over by attackers.