25 comments

[ 5.6 ms ] story [ 89.0 ms ] thread
malloc is special in environments that aren't free-standing, the compiler can assume that the pointer that malloc returns doesn't alias any other at that point.
Though with most compilers, there are ways of making other functions similarly special.
I am not familiar with 'free-standing', though, I think that malloc in most environments never returns the same pointer twice (an alias). Though I may misunderstand your point.
C++11 1.4 [intro.compliance]/p7 "A freestanding implementation is one in which execution may take place without the benefit of an operating system, and has an implementation-defined set of libraries that includes certain language-support libraries" [1]

C11 4 [conformance]/p6 "A conforming freestanding implementation shall accept any strictly conforming program in which the use of the features specified in the library clause (clause 7) is confined to the contents of the standard headers <float.h>, <iso646.h>, <limits.h>, <stdalign.h>, <stdarg.h>, <stdbool.h>, <stddef.h>, <stdint.h>, and <stdnoreturn.h>." [2]

[1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2011/n324... [2] http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf

"The GC language is carpet bombing your memory, your performance."

Occasionally, the book-keeping to make sure you're able to clean up each allocation individually can be higher than the overhead of garbage collection. Of course, if you're working in C, you can just add garbage collection, either globally (Boehm collector, say, though I don't know how well it actually performs) or only for some particular resources (though then you do need to be sure you are tracking your roots appropriately).

I always find it amusing when I write something that spends a bunch of work making sure everything is freed before it exits. (It's worth doing so valgrind can help you be more confident you're freeing what should be freed as you go along.)

"I always find it amusing when I write something that spends a bunch of work making sure everything is freed before it exits."

Yeah, just exit! That's the kind of cool thing about these small, short lived Unix programs like grep and cat - chew memory (stack or heap, up to you!) and bail out - let the OS clean it up. It is essentially the same argument as "prefer large mallocs to small" - the process itself is a 'large malloc'.

Right. Like I said, the reason to go to the (programming) effort is that I can make sure it valgrinds clean, which means (if I'm being moderately smart along the way) that I'm not dropping things on the floor that I don't mean to during the program run when I still care about it. Adding a flag for "I don't care about valgrind, go ahead and exit" is then a tiny bit of extra programmer work to save the processor a bit of extra work each run; not sure it's worth it but not sure it's not.
Valgrind looks like an amazing tool. I am still a bit giddy to use a C with function prototypes, // style comments and enums, to be honest.
Valgrind and friends are great.

splint has been useful, but needs c99 (and now c11) support.

Tangential, but one thing I've recently taken to doing in my C is basically avoiding bare primitive types, preferring to wrap them in a single element struct. This means I can't pass, for instance, price where I mean quantity just because they're "both numbers".

An article not reviling static languages and encouraging people away from ruby/python? On my Startupnews?
What the *&^@ is a "static language"?
Well, truth be told, I'm a bit of an interloper. I'm quite old and C is my 'native tongue', although I haven't really programmed in it for years, until recently.

At the beginning of my career, I spent fourish years professionally writing K&R C. Before that I had convinced my profs that I could submit my assignments in C rather than the mainframe Pascal that was being used by the other students. The balance has been spent in Smalltalk, Java, Python, etc.

I must say that I really like the re-adjustment. Even though there are 'endless banks of RAM', C forces the programmer to be stingy with memory and come up with neat hacks, simply to avoid the enormous pain of being too clever.

Using malloc() is like lying. You've got to remember them all.

"Maybe it's speed, though I really wonder about that, given our blistering fast processors and endless banks of RAM"

I've seen this thought hundreds of times over the last decade, and I don't think it's a very good one. If execution environment A is twice as fast as B, it will still be twice as fast after the processor speed doubles. Mostly, we usually want to do as much as we can with the hardware we have.

If A is twice as fast as B, it'll save you half as much time after the processor speed doubles.
And the endless banks of RAM aren't really all that helpful to performance when it still takes eons to actually fetch the bits from them.
If you're creating an IO bound application (e.g. Dropbox, most web sites) then the developer time gained may be worth the performance offset.
If we are looking at the universe of Rails and Python programmers coming to C, then yeah, I think we can assume they aren't doing it for the exotic address manipulation operations and their colleague's prestige ;)

It's speed.

It is also almost always interesting. It reveals a boundary that has been crossed, a bottleneck plugged. I think that us HLL devs always like to think we have C in our back pockets. We say, "well if performance is bad we will profile then rewrite that bit in C". Then, when faced with the reality of actually having to write something in C, well it's a different story. We think the performance increase will be dramatic, but often we are left with something that performs worse than the original HLL equivalent, and that leaks memory and frequently crashes to add insult to injury!

There's also static allocation, though viewing that as happening in a stack frame above main seems not unreasonable.
The scope is very different, so that may be a misleading way to view file statics and globals.
That's certainly the case. It makes sense in terms of allocation pattern, but there are other distinctions to be preserved.
As a long-time Java guy who just started learning C over the past few months, I've found it very valuable in understanding how some of the under-the-hood details which are hidden by the higher level languages actually work. Learning a low level language and pricking yourself with a few pointers makes you a better programmer, even if you never write a big app in it.
The best thing about C for a long time has been that it has precious few hipsters trying to fuck it up. Please stay away, hipsters.

P.S. I heard the ECMAScript mailing list needs more suggestions for the garbage heap of "improvements" they plan to dump into the next version.

I don't think there is something inheritantly wrong with a lib allocating on your behalf. Most non-trivial problems require memory allocation, and if you have a struct that has dynamically allocated fields (like char*'s of data derived from files you've read in), often providing a ${structname}_new() and ${structname}_free() pair is less mental overhead than making sure to free certain fields in stack-allocated structs.
I don't know exactly what the author is referring to, but I know that C is unique in that it will never go away. So long as new hardware primitives come into play, we will always need to return to the level of C to squeeze out performance. This will only become more and more true as the ascendancy of multicores continues. A buddy and I were thinking about it just the other day: could you even imagine a closer wrapper for assembly with comparable ratios of effort to level of control?
Machine language won't go away either. It's just that the only people writing it are compilers.

The article was more about: Python programmer meets C, C introduces him to malloc(), programmer falls in love with malloc, C gets jealous and in a fit of rage deallocates programmer.

I think this extended love affair for C comes from the fact that it's the least-common-denominator in terms of what our OSes are written in. At some point everything has to make system calls that are using C calling conventions and data structures. It makes sense that the base layer of everything will be written in C. It's an historic anomaly, not some fundamental awesomeness of the language itself.

That said, it's a fundamentally awesome language, especially to build OSes in, but that's tangential.