Memory safety

I am leaning c++ programming, i have experience programming in high level languages (JavaScript, php and python). After reading about c++ i found out that that you need to be careful with memory management or you can cause think like Buffer overflows, Memory leaks and other thinks found here https://en.wikipedia.org/wiki/Memory_safety. I also found that in modern c++ there are thinks like smart pointers, containers, constructors and destructors, etc. that help mitigate a lot of memory related issues if used correctly. If i program using these modern features what are the memory related pitfalls i need to be aware of and avoid, examples and explanations of incorrect and correct scenario are appreciated.
IngerAlHaosului wrote:
in modern c++ there are thinks like smart pointers, containers, constructors and destructors

none of that is really "modern": constructors and destructors (and, consequently, RAII - read http://en.cppreference.com/w/cpp/language/raii if you haven't yet) were in C++ since the beginning. Containers and smart pointers are just concrete examples of RAII and also aren't new: containers were part of C++ since the first standard (1998), smart pointers were fairly new in the 90s and were rejected by the standardization committee back then (except for auto_ptr), but were so successful in boost and third-party libraries through the 00's that they were merged to the standard C++ as soon as it was possible (in 2011).

If i program using these modern features what are the memory related pitfalls i need to be aware of and avoid

Losing sight of ownership is probably the biggest pitfall beginners run into after they learn about std::shared_ptr and start using it inappropriately (that is, like a managed pointer in a gc language). Once you learn to program without ever calling new or delete (which is a characteristic of modern C++ style), try programming without using std::shared_ptr unless there really are multiple owning threads with non-deterministic lifetimes.
Last edited on
wiki wrote:
For example, Java is said to be memory-safe because its runtime error detection checks array bounds and pointer dereferences.[1] In contrast, C and C++ support arbitrary pointer arithmetic, with no provision for bounds checking,[2] and thus are termed memory-unsafe.[3]


Statements like that taken at face value are misleading IMO. It makes it sound as though C++ is like C and therefore thoroughly unsafe, which is very unfair. For example, one can do quite a lot if one does all of their code using STL containers and their functions and algorithms. The STL does it's own memory management, so that takes a lot of the worry away

I think this comes from C++ being a multi paradigm language: One can write C code with raw pointers and pointer arithmetic; hell, even put assembler statements. On the other hand there is the STL and some very clever things to be achieved via template meta programming.

C++ is improving all the time, for example there are concepts in C++17.

So, in conclusion the situation is not as dire as it sounds.
TheIdeasMan
It makes it sound as though C++ is like C and therefore thoroughly unsafe, which is very unfair.

C++ is much unsafer than Java or .NET. There is lots of undefined behaviour, like accessing a vector or array out of range or passing a wrong iterator to an algorithm.
@Thomas1965


Yes, that is fine. But how about saying that C++ with the STL is somewhere between C (where almost anything goes, and one has to be commensurately careful) and Java / .NET. I guess I was objecting to the idea that C++'s lower level capabilities means that it's safety is also at the low end. In other words C++ is less safe than Java, but not disastrously so.

I don't know much about Java / .NET, what happens exactly for these runtime checks, say for out of bounds access? Is it particularly useful to discover that at run time? Is it like a message box which comes from some kind of exception? Would it not be better to do checks and prevent the errant access in the code?

In Cpp Core guidelines there is discussion and a link to the GSL library, which does things like bounds checking.

As I said earlier, I think is misleading to take the above statement at face value - while it is true, there is more to it.
@TheIdeasMan,

In other words C++ is less safe than Java, but not disastrously so.

Yes I agree.

what happens exactly for these runtime checks, say for out of bounds access?

In Java and .NET you get an ArrayIndexOutOfBounds exception at runtime. If you don't catch it in Java an error msg gets printed to the console. In .NET you get the Windows box: "The programm .. has stopped" with the option the close or debug it.

Of course it would be better if this things could be detected at compile time but neither the Java nor the C# can do it. But an exception is IMHO much better than undefined behaviour - especially if you use unit tests.

One can write C code with raw pointers and pointer arithmetic;

Sometimes you do it even in modern C++ like:
1
2
3
4
5
6
7
8
9
template<class T>
void YourSuperDuperAlgorithm(T first, T last)
{
  while (first != last)
  {
     // use *first
    ++first;
  }
}

where it is not so obvious that T might be a raw pointer like vector::begin().

Modern C++ is much safer than the old C.
I just wonder if it gives developers a wrong sense of security. Recently I read on a newsletter that Goole Chrome has a buglist with 3000+ entries despite using latest C++.
@Thomas1965

I guess that it is quite involved to write robust code, probably no matter what the language is. People write quite safe highly reliable C code, but I imagine there is quite a bit of effort involved to do so. So there are expert coders who can recognise all types of UB, know what can throw etc, and code accordingly. It's a problem for lesser beings that aren't aware of all the good practises.

Perhaps the difference between languages is in things like C++ has range based for, where C doesn't (but one could enforce it with extra effort). Java has bounds exceptions, C++ doesn't quite yet have in the standard (is it coming in C++20?), but one could use the GSL library, or write their own exception to do so.

Another idea is that I gather quite a high percentage of code is there to make it robust - maybe even 75%

More about the experimental constraints and concepts, which work at compile time:

http://en.cppreference.com/w/cpp/language/constraints

There is support for this in g++ 6.3 and clang++ 3.9.
Ill be the one to say it, also: all that checking and babysitting of the programmer by the language has a performance cost. Its not as critical as it was when these languages came out and has almost zero impact on modern machines for most code, but the option is there if working on a weak embedded system or something.
Topic archived. No new replies allowed.