Live data from Hacker News

In C, how do you know if the dynamic allocation succeeded?

lemire.me

31–40 of 198 posts

Re: In C, how do you know if the dynamic allocation succeeded?

#31

Earlier quoted context omitted.

wouldn't you just account the COW pages against the parent until they are copied? kicking the can down the road means there isn't any longer a reasonable correction (failing the allocation), but instead we get to drive around randomly trying to find something to kill. this is particularly annoying if you are running a service. there is no hope for it to recover - for example by flushing a cache. instead the OS looks…

Indeed. It's totally dumb that the OS is allowed lie to you when you've asked for some resources. And because of this behaviour people no longer check for success from malloc(), etc, because of laziness. It's a bad situation.

Allocated-but-unavailable is a totally reasonable part of the memory hierarchy.

Main Memory => zswap (compressed memory) => swap

In this case, the pages may be logically allocated or not -- the assurance is that the data will be the value you expect it to be when it becomes resident.

Should those pages be uninitialized, the "Swapped" state is really just "Remember that this thing was all zeros."

We could do computing your way, but it'd be phenomenally more expensive. I know this because every thing we introduce to the hierarchy in practice makes computing phenomenally less expensive.

Re: In C, how do you know if the dynamic allocation succeeded?

#32
post #14

This is why some embedded systems don't do malloc (IIRC...been a while since I've read much about those).

Embedded systems (the ones where you would disallow malloc) don't generally have virtual memory by virtue of having no MMU, so on those you can't do overcommitment since there is no page fault mechanism.

No, the reason is simply that by statically allocating all memory you can avoid entire classes of program faults and bugs. There are no memory leaks and you don't need to solve the NP-complete problem of "is there an execution path where a dynamic memory allocation will fail". Keep in mind that it is not just about the total amount of dynamically allocated memory, but also the order of allocations (and frees).

Re: In C, how do you know if the dynamic allocation succeeded?

#33
post #24
post #13

One of my interview questions starts with "Can a program allocate more memory than is physically available on the server?" Everybody gets this wrong (which is funny for a binary question) but it starts an interesting discussion through which I hope to learn how much they know about OS and virtual memory.

Don't leave us hanging. The "obvious" answer would seem to be "yes" because of swap. But if everyone gets that wrong...

No, it's worse than that - the answer is "yes", because virtual memory + overcommit means that most of the time the OS will happily allow you to allocate more memory than physical+swap, and essentially gamble that you won't actually need all of it (and this is implemented because apparently that's almost always a winning bet).

Re: In C, how do you know if the dynamic allocation succeeded?

#34

TLDR: "You don't." (Because malloc hands you virtual memory and actually trying to use it might reveal that the system doesn't have the real memory to handle your request. I kept reading hoping that there was going to be a solution, but not really; there are comments discussing disabling overcommit, but even that's a tradeoff (it does fix this failure mode, but you might not want to actually run a system like that).

There's gotta be some way to programmatically determine it, right? It may not be portable. It may require some system calls or something, but there's gotta be a way, right?

I'm not an expert enough to tell you; I just read the article and decided that it was too long so summarized for others. There's some discussion upthread about catching SIGSEGV and other methods, FWIW.

Re: In C, how do you know if the dynamic allocation succeeded?

#35
post #14

This is why some embedded systems don't do malloc (IIRC...been a while since I've read much about those).

I wouldn't say this is the reason. Embedded systems typically don't have virtual memory to start.

I would expect (but verify) a malloc implementation on embedded to return null if it can't satisfy the allocation.

But even with that assumption malloc in embedded is often a bad idea. You need to plan for worst case anyway and you can not afford memory fragmentation.

Re: In C, how do you know if the dynamic allocation succeeded?

#36

Earlier quoted context omitted.

Indeed. It's totally dumb that the OS is allowed lie to you when you've asked for some resources. And because of this behaviour people no longer check for success from malloc(), etc, because of laziness. It's a bad situation.

Allocated-but-unavailable is a totally reasonable part of the memory hierarchy. Main Memory => zswap (compressed memory) => swap In this case, the pages may be logically allocated or not -- the assurance is that the data will be the value you expect it to be when it becomes resident. Should those pages be uninitialized, the "Swapped" state is really just "Remember that this thing was all zeros." We could do computing…

"We could do computing your way, but it'd be phenomenally more expensive"

It must be viable - Windows prevents overcommit. But it has slow child-process-creation (edit: previously said "forking"), and this steers development towards native threads which is its own set of problems.

I had never previously joined the dots on the point pcwalton makes at the top of this thread. It is a dramatic trade-off.

Re: In C, how do you know if the dynamic allocation succeeded?

#37
post #24

Earlier quoted context omitted.

Don't leave us hanging. The "obvious" answer would seem to be "yes" because of swap. But if everyone gets that wrong...

No, it's worse than that - the answer is "yes", because virtual memory + overcommit means that most of the time the OS will happily allow you to allocate more memory than physical+swap, and essentially gamble that you won't actually need all of it (and this is implemented because apparently that's almost always a winning bet).

Yeah. And the issue is that the actual problem happens sometime later when the application actually tries to use that memory. So you replaced an error that is relatively simple to handle with something that is impossible to handle reliably.

So the operating system very much doesn't like to admit it doesn't have physical memory to back the area you are trying to use. Now it does not have a simple way to signal this to the application (there is no longer an option to return an error code) and so either everything slows down (as OS hopes that another process will return a little bit of memory to get things going for a little while) or one of the processes gets killed.

Re: In C, how do you know if the dynamic allocation succeeded?

#38
post #6

I once complained about malloc happily allocating memory that the physical memory system couldn't satisfy (never let your hand write a check your ass can't cash?) but the more experienced programmer asked me if I'd heard of fractional reserve banking, and if not, whether it bothered me too.

If you're smart, the answer is yes, over reliance on statistical multiplexing scares the shit out of you, because it's all fun and games till the check is due.

Re: In C, how do you know if the dynamic allocation succeeded?

#39
post #12
post #6

I once complained about malloc happily allocating memory that the physical memory system couldn't satisfy (never let your hand write a check your ass can't cash?) but the more experienced programmer asked me if I'd heard of fractional reserve banking, and if not, whether it bothered me too.

Not the same thing. malloc() can tell everybody it has the memory but when push comes to shove the OS will have to admit overbooking.

TIL, unless you explicitly disable memory overcommit, it can and will overcommit.

This is crazy to me.

Re: In C, how do you know if the dynamic allocation succeeded?

#40

It's important to remember the biggest reason why overcommit exists on Linux and macOS: fork(). When a process forks, the vast majority of the child process's memory is safely shared with the parent process, due to copy-on-write. But a strict accounting would say that the total memory usage of the system has doubled, which is too conservative in most cases. Since forking is so common on Unix, overcommit ends up being…

> Otherwise, fork/exec would stop working in any process using more than half of the system memory.

Somehow Solaris manages just fine.

And don't forget that swap memory exists. Ironically, using overcommit without swap is asking for trouble on Linux. Overcommit or no overcommit, the Linux VM and page buffer systems are designed with the expectation of swap.

Post reply on HN