[1] handles could be unboxed to expose a pointer. But unboxing had machinery to detect and trap on bad handles
Edit: that static allocation was essentially a centralized store. Everything repeats itself.
https://floooh.github.io/2018/06/17/handles-vs-pointers.html
You've already been greyed out, but I agree 100% with what you said.
That's my main beef with this kind of bi-weekly discussion where people always put C and C++ in the same bag.
I rarely, if ever, make memory management errors in C. The model can't be more simple. If you don't explicitly allocate, you don't have to care about it (in the general case, it is on the stack and will disappear when exiting a function, anyway you also don't have to care about those implementation details, just do as if it disappeared with scope). If you allocate something (on the heap), then you free it later. Malloc(), free(), end of story. Okay, don't keep pointers to areas you will free or realloc, of course. Any function which returns pointers tomemory chunks are always to be treated as malloc'ed, those objects can never be on the stack and never have a fancy automatic management of any sort.
Now almost each piece of code I wrote in Objective-C contained memory errors/leaks. Be cause 1. I didn't grasp the more complicated, less deterministic (so to speak) models and the jargon well 2. you (well, I) never know right away which type of management was used for the object that some function returned, you have to check the doc and pray it is clearly written 2.b you have to keep that information in mind until the moment when you'd like to release the said object in order to release what should be released and not release what is/will be/has been automatically released now/later/sooner/whoknows.
And I don't even talk about the abomination that is Objective-C++, where I drowned in muddy waters.
This is where I make the case for having knowledge of asm/C/C++. The JavaScript developers that started on JavaScript or, maybe, Ruby have no clue what the hell is going on in the language they are working in. I see this all the time. From senior and lead developers, too.
They have no mental model for how pointers work. Which means they have no concept of what an object is, on a memory-organization level. They aren't always aware of when mutation will occur, and they are entirely too reliant on operations that are inefficient. In Lisp, this would be the developer than uses CONS everywhere. There is no awareness of the allocations behind the mechanisms. There is premature optimization and then there is not driving into the damn pothole in the first place! One of these is F1 racing and the other is basic driving skills.
I believe this may also explain why so many developers are so bad at using git. Git is entirely based on pointers. There is an elegance and simplicity to git that is lost on many people.
In the old days people usually chose to become a programmer for a reason, today it is like any other job.
Just like you can be a very effective C or C++ developer without knowing anything about css (which in my opinion is far more difficult to understand than when and how stack vs heap allocations are made)
Yes, exactly.
https://kkimdev.github.io/posts/2019/04/22/Rust-Compile-Time...
Of course, you can bypass this by using 'unsafe' code, where you are explicitly telling the compiler that you have manually verified Rust's safety guarantees.
This is why a significant portion of Rust's community gets agitated with (possibly unnecessary) use of 'unsafe' in popular libraries.
Considering many of the software problems we face have some connection to thread-safety, Rust is the way to go.
Threading seemed a good idea that went wrong.
Then you are back into the same synchronization issues as in every other language.
I'm trying to learn Android and some libraries give zero indication of what thread your callbacks will be called on.
Maybe there's a convention somewhere that says "On Android, you can't assume anything about callbacks, so always assume you're on some anonymous worker thread and lock everything or dispatch to a thread you own"
But I have not come across it yet.
You cannot assume anything about process or thread lifetimes on Android, as the simple act of rotating the screen will restart your application, and it can be killed at any moment and restarted later, due to memory pressure, or because the use has switched applications.
So whatever was the state of your application can be completely different when the callback is supposed to be invoked later on.
As for having more time to write a fast program... that's funny. If you want a fast program on something JVM based you're pretty much going to be spending the majority of your time writing things in a way where the GC plays as little role as possible.
Sorry, this is not hand wavy nonsense. And what you are providing is called annectodal evidence.
Also, your universe seems to consist only of the JVM as a memory-safe alternative to C++. Yes, there are a lot of bloated, badly performing programs implemented in Java. However this isn't a given. Yes, some design decisions for Java introduce the risk of bloat, but you can avoid them at much less effort (and risk) than memory corruptions and new features like the value classes are reducing the bloat quite a bit. But still, the JVM is extremely high performance, so for speed in surprisingly many cases, it often beats C++. Virtual method calls are just better optimizable at run time, the Java JIT creates excellent code and Java has some of the best garbage collectors, so at really dynamic memory loads, it beats any manual management by a wide marging.
And of course, there is a whole world beyond Java as alternatives. Rust has been explicitly designed to excel at tasks C++ traditionally shines for, while giving your full safety.
Rust is certainly interesting and it's on my radar. I wonder though, when it comes to having it in use in anger if its guarantees turn out to be over sold, just like the JVM's safety claims were. Time will tell.
Edit: I tend to focus on comapring against the JVM because pretty much any framework you use on The Cloud is JVM based. I'm of the opinion that there are cost savings to be had if these were ported to more appropriate languages, hence the Cassandra vs Scylla comparison. The money saved was 'noticeable'.
[1] https://github.com/LMAX-Exchange/disruptor [2] http://mishadoff.com/blog/java-magic-part-4-sun-dot-misc-dot...
Java 15 just accepted the JEP for native memory management, yet another stepping stone for having value types support.
If the cadence continues, Java will eventually have all the features that it should have had in 1996, had Sun properly taken into consideration languages like Modula-3 and Eiffel.
Which you can get today in a language like Swift, C#, Nim or D, productivity of GC, type safe, while having the language features to do C++ like resource management.
You'll never actually see anyone tout the benefits of using GC for this, though, because the performance characteristics of persistent data structures are so horrendous compared to mutable ones, no one actually uses them in C++.
Of course, repeatedly allocating and freeing is poor for performance. Cache/pre-allocate when you can. This goes for managed languages too.
Stack is also very hot in cache. Memory that GC is handing allocations from is not.
I recently ported some of Cassandra code from Java to stack-only Rust and I got ~25x performance improvement, most from avoiding heap allocations and GC.
Both Java and C# may be somewhat slower, but the maintainability and freedom from memory management issues more than makes up for this.
Any engineer worth his salt will take this into account.
If you unlucky and given GC is not well optimized for given workload, then memory usage overhead can be huge. Just a few days ago had such problem with Go (HeapIdle grew until OOM).
Go GC is less mature than Java GC, but Java GC is not free too - sometimes you need to spend a lot of time time to tune GC settings or to optimize code to avoid GC problems.
In my case case it would be faster to use malloc/free than to spend time fighting with GC (looking for a workarounds).
On average GC saves development time and allows to avoid memory management bugs, but in some cases overhead is big and developers have to spend more time, not less.
https://www.ptc.com/en/products/developer-tools/perc
https://www.aicas.com/cms/en/JamaicaVM
One of the Java vendors acquired by PTC, Aonix, used to sell real time Java implementations for military deployments, including weapons controls and targeting systems.
You don't want a couple of ms pause when playing with such "toys".
If you mean the `synchronized` keyword, then correct, they don't have that. Most languages do not have that concept. C++ does have mutexes and has had them since C++11 (nearly a decade). C++ also has as part of the language spec the concept of threads, again, there since C++11.
If you meant co-routines, then C++ just added them with C++20.
Or do you mean something different like green threads (ala go)?
C++ certainly has concurrency constructs and has been expanding them since C++11.
The entire design of C++ is to enable efficient libraries for these kinds of things to be built. And it does, and has, and will continue to for decades more.
And ?
C (even Fortran) had threads and was used to create high performance program with high degree of parallelism before any "concurrent" modern language was even born.
You can not agree if you want. But fact are there, 98% of programs running on the biggest "parallel" machines nowadays (supercomputers) are C, C++ or Fortran.
You don't need to be "designed" concurrent to be efficient at it. The same way you do not need to be designed "Cloud-native (bullshit)" to run on a virtual machine.
We have to give programmers, with different backgrounds & training, tools to write high performant code in their everyday job. Many of the tools we use today are not designed for that. We are stuck in a mental model 50 years old that is no longer true.
Here are some interesting stackoverflow answers. You are of course free to dismiss these answers as anecdotal.
So much that in the 90's there were vendors that could make a business out of selling specialized memory allocators.
https://inf.ethz.ch/personal/wirth/ProjectOberon/Sources/Ker...
The malloc() exposed in a ISO C standard library implementation isn't necessarily related to whatever means the OS does memory allocation.
What C and C++ have going for them is 40 years of investment in optimizing compilers, to detriment of other languages, and abuse of UB in optimizers.
Now with shared compiler backends becoming a mainstream thing across most OSes, that advantage is getting thinner.