It still does, because it future proofs you against a change in the future that separates the allocation from completely filling the memory, and saves you from future programmers who don't realize that only half-filling the memory could have catastrophic security or correctness consequences. It also harmonizes the programmer's mental model (which has generally always assumed that newly-allocated memory is "clean" even when on some level we theoretically know better [1]) with the execution model, which is also a good thing.
I'd very much recommend that advice; use it all the time, remove it only when it proves to be a problem, and then, as always when optimizing, bear in mind that you've chosen to juggle lit sticks of dynamite and prepare accordingly.
[1]: I hypothesize that this is because what "really" comes back from a malloc is basically too impossibly complicated to model by a human. Even calling it "random" isn't correct; it's not random, but what it is is very hard to characterize.
My mental model of memory in C is that it is unitialized unless otherwise specified. Certainly in higher level languages (e.g., Java, Pyton, Ruby), we expect memory to be initialized (otherwise garbage collection doesn't work).
Coming to C with a mental model of memory from another language is a recipe for security problems.
Then you use valgrind instead of sweeping bugs under the rug.
The next person may have equally likely (or maybe more likely?) simply forgotten to initialize some particular field and now you've got a problem if the field is supposed to read 0 most of the time and maybe sometimes 1.
When you're using Valgrind and ASan, the "calloc for safety" advice becomes backwards. calloc defeats such instrumentation, because heap memory isn't uninitialized anymore.
> It still does, because it future proofs you against a change in the future that separates the allocation from completely filling the memory, and saves you from future programmers who don't realize that only half-filling the memory could have catastrophic security or correctness consequences.
But how does replacing that radioactive waste (neat analogy) with zeros improve correctness here?
Which is all to say: It doesn't improve correctness at all. You improve correctness by making your interface difficult to use incorrectly, not by limiting the bad effects of incorrect usage. And any time your code accesses memory that is for all intents and purposes undefined (which it still is, even if you overwrite it with zeros that have no semantic intention behind them), your code is behaving incorrectly by definition.
> I hypothesize that this is because what "really" comes back from a malloc is basically too impossibly complicated to model by a human. Even calling it "random" isn't correct; it's not random, but what it is is very hard to characterize.
I think "uninitialized" is the word you are looking for :)
No, it's not. That deceives programmers into thinking "oh, it's just some random garbage", but it's not. It's not random, and it's not merely "garbage". It's an incredible interplay between the exact allocation patterns of your program and user input, and results in that glossy word "uninitialized" including things like "user passwords", "private keys", "shell code" (that is, attacker-supplied arbitrary assembly code), and arbitrary other non-garbage information that you may not appreciate having at at this point in the program that is completely oblivious about what is in that "uninitialized".
Uninitialized isn't "a mess that you really ought to clean up before using", it's radioactive waste.
If you want to tell me that you really do think of "uninitialized" that way every time you use it, I have no grounds to disagree with you personally... but based on the code in the wild, it does not seem that most C programmers do have a correct understanding of the issue.
(People who develop the proper level of concern about handling radioactive waste tend to find ways to stop programming in languages that don't default to handing back nuclear waste on every memory allocation. I suspect some form of evaporative cooling may be a problem here.)
I'd very much recommend that advice; use it all the time, remove it only when it proves to be a problem, and then, as always when optimizing, bear in mind that you've chosen to juggle lit sticks of dynamite and prepare accordingly.
[1]: I hypothesize that this is because what "really" comes back from a malloc is basically too impossibly complicated to model by a human. Even calling it "random" isn't correct; it's not random, but what it is is very hard to characterize.