Live data from Hacker News

Why does calloc exist?

vorpus.org

31–40 of 141 posts

Re: Why does calloc exist?

#31

Earlier quoted context omitted.

I think there's a big difference between "why does ... exist" and "why does ... still exist". calloc() may be useful today for reasons completely different from why it existed in the first place. And the difference #2 is just an implementation-specific optimisation. There's nothing in the standard that forces calloc to use lazy allocation / virtual memory. Actually, it may be implemented on platforms which can't prov…

Thank you for bringing up the implementation-specific nature of #2! If the author is running Linux, then perhaps they've never checked out overcommit vs. not overcommit.

The way malloc, calloc, and memset are implemented all are implementation specific. For example, memset, when asked to zero memory, may use cache control instructions such as https://en.wikipedia.org/wiki/Cache_control_instruction#Data....

That tells your cache "pretend that you read all zeroes into the cache line at this address, and mark it as dirty (that guarantees the zeroes will be written out, even if the caller doesn't write to the cache line)

For small amounts of memory that will be written to soon, that's as good as free since it doesn't have to read from memory (the naive loop will, as it has to bring in an entire cache line before it can zero out its first byte or word)

Re: Why does calloc exist?

#32

    buf = calloc(huge, huge);
    if (errno) perror("calloc failed");
    printf("calloc(huge, huge) returned: %p\n", buf);
    free(buf);
This has a flaw. errno doesn't magically get reset to zero. You should check the return value of calloc, then use errno. Checking if(errno) is not the right way to determine if there was an error.

Re: Why does calloc exist?

#33
post #3

That's a nice alternative history fiction. Here's an early implementation: https://github.com/dspinellis/unix-history-repo/blob/Researc...

You haven't proven it wrong.

Here's the earliest implementation in that repo (in Research UNIX V6; your link in V7): https://github.com/dspinellis/unix-history-repo/blob/Researc...

    calloc(n, s)
    {
    return(alloc(n*s));
    }
There are several interesting things we learn from poking around V6 though:

- `calloc` originated not on UNIX, but as part of Mike Lesk's "iolib", which was written to make it easier to write C programs portable across PDP 11 UNIX, Honeywell 6000 GCOS, and IBM 370 OS[0]. Presumably the reason calloc is the-way-it-is is hidden in the history of the implementation for GCOS or IBM 370 OS, not UNIX. Unfortunately, I can't seem to track down a copy of Bell Labs "Computing Science Technical Report #31", which seems to be the appropriate reference.

- `calloc` predates `malloc`. As you can see, there was a `malloc`-like function called just `alloc` (though there were also several other functions named `alloc` that allocated things other than memory). (Ok, fine, since V5 the kernel's internal memory allocator happened to be named `malloc`, but it worked differently[1]).

[0]: https://github.com/dspinellis/unix-history-repo/blob/Researc... (format with `nroff -ms usr/doc/iolib/iolib`)

[1]: https://github.com/dspinellis/unix-history-repo/blob/Researc...

Re: Why does calloc exist?

#34
post #30

Sorry, but this is just goofy and bad. If you depend on copy-on-write functionality, then you need to use an API that is specced to guarantee copy-on-write functionality. If that means you use an #ifdef per platform and do OS-specific stuff, then that is what you do. Anything else is amateur hour. If copy-on-write is a desirable feature, then as the API creator, your job is to expose this functionality in the cleares…

I think the author's point is opportunistic optimization. He didn't ask us to rely on this behavior.

Re: Why does calloc exist?

#36
post #30

Sorry, but this is just goofy and bad. If you depend on copy-on-write functionality, then you need to use an API that is specced to guarantee copy-on-write functionality. If that means you use an #ifdef per platform and do OS-specific stuff, then that is what you do. Anything else is amateur hour. If copy-on-write is a desirable feature, then as the API creator, your job is to expose this functionality in the cleares…

Neither copy on write nor size checking are specced as part of the calloc() definition.

Here's the specification of calloc from the ISO standard:

  7.22.3.2 The calloc function

  Synopsis

    #include 
    void *calloc(size_t nmemb, size_t size);

  Description
  
  The calloc function allocates space for an array of nmemb objects, each of whose size is size. The space is initialized to all bits zero.
  
  Returns

  The calloc function returns either a null pointer or a pointer to the allocated space.

Re: Why does calloc exist?

#37
post #11

Earlier quoted context omitted.

I think he was referring to the part where a calloc'd memory page will be zeroed the first time it's used, rather than all at once at the beginning. In a real-time system, the start-up time matters less than having predictable response times.

In a realtime system you can't use virtual memory because the access times are unpredictable.

I specifically avoided that word because it triggers particular deadlines that people have in mind. If my application requires no more than X ms latency I don't care to handwring over realtime vs soft realtime vs whatever, but it's still critical to fit in the budget. But indeed you can get reliable low-latency products to work on linux, with virtual memory. But like I said pinning is a great way to keep those peaks down.

Re: Why does calloc exist?

#40
post #12

> Plus, if we wanted to, we could certainly write our own wrapper for malloc that took two arguments and multiplied them together with overflow checking. And in fact if we want an overflow-safe version of realloc, or if we don't want the memory to be zero-initialized, then... we still have to do that. Like reallocarray(3) does? buf = malloc(x * y); // becomes buf = reallocarray(NULL, x, y); newbuf = realloc(buf, (x *…

reallocarray(3) looks nifty, but until it's available on a wider, ideally more standard-driven basis than just OpenBSD and FreeBSD, it's likely to not see wide uptake.

It's already gaining adoption outside of the BSDs. OS X/iOS seem to have it as part of their libmalloc. Android Bionic libc has it as part of the code they sync from upstream OpenBSD.

Many open source projects include their own, or simply bundle the OpenBSD implementation:

  * mandoc
  * flex
  * unbound and nsd
  * tor
  * tmux
  * libbsd
  * libressl
  * xorg-xserver
  * ...
The list only continues to grow, several more examples to be found on GitHub.
Post reply on HN