Live data from Hacker News

Malloc Never Fails (2012)

scvalex.net

91–100 of 165 posts

Re: Malloc Never Fails (2012)

#91
post #73
post #68

This assumption lead to Rust's standard library not having a way to catch allocation failures (which is only now being rectified, and only partially). It's very Linux-centric and presumes a certain config+usage pattern. Not true on Windows. Not quite true on macOS. Not true in WASM. Definitely not true on embedded platforms.

Is there somewhere to read about how rust is tackling this problem?

It seems to be described in this Rust RFC: https://github.com/rust-lang/rfcs/blob/master/text/2116-allo...

Re: Malloc Never Fails (2012)

#92
post #54

Earlier quoted context omitted.

> ask the user You just failed to create a toolbar button, how are you going to ask a user do something if you already failed to create a tiny UI element?

I guess you pre-allocate these UI elements when you start your application.

What if malloc fails at that point because some other application (we're in a preemptive multitasking OS) decided to gobble up all RAM?

Re: Malloc Never Fails (2012)

#93
post #36

Earlier quoted context omitted.

In practice i haven't seen any application to gracefully handle out of memory situations. Even back in Windows 3.x days when running out of memory was common, most applications simply hanged or crashed (which also took the entire GUI with them) and those that didn't often had a "no memory, kthxbye" dialog that shut down the application. A very few rare cases would try to display some "sorry, no memory, close some pro…

What is your definition of graceful in this case? Presumably there was a “business need” for the allocation and the software isn’t just allocating for fun. An allocation failure is a hard fault, it’s not possible to honor the business need so something expected to happen cannot happen. The program could segfault when the null pointer returned is written to, that is kind of crappy. It could report the error “hey we ar…

> It could report the error “hey we are out of memory and couldn’t do xyz” or better “hey we are out of memory and couldn’t do xyz, this is probably because of abc, maybe you can adjust the tuning.”

What if you cannot do that report because the reporting itself needs memory that can fail?

> but yes you should put a check on every toolbar allocation for two reason: one you can gracefully report why your app isn’t doing it’s job

This is a reason to put checks in every toolbar allocation, but on the other hand there is also a reason to not do that: you are trying to catch a case that will only happen at a 0.00001% of the time yet to do that you are making the codebase more complex which will affect working with it 100% of the time.

Unless you are working in something like a medical or nuclear device, it is not worth to bother with such things. Even then when it comes to high risk programs relying on the programmer doing things right outside the core functionality is probably (i haven't worked on such projects myself so i'm guessing here) not a good idea and instead you should compartmentalize (e.g. the core functionality is running as a separate process from the UI and if the UI crashes, a watchdog restarts the UI process). But that is my guess here, i mainly have common end user/consumer applications in mind.

Re: Malloc Never Fails (2012)

#94
post #57

Earlier quoted context omitted.

It's a shame that turning off overcommit is done at the system level, rather than the malloc call level. Some applications, and perhaps some allocations within otherwise naive applications, might prefer to have an allocation fail early, where failure could be sensibly handled.

There is some support for this actually. Namely, when overcommit_memory is set to its default value (0), then it actually implements a heuristic for overcommit. (Where as the value `1` corresponds to "always overcommit.") Namely, only when overcommit_memory is set to 0, if you allocate memory with mmap and pass the MAP_NORESERVE option, then allocation behaves as if overcommit is always enabled and there is no check.…

The OOM killer can strike at any time, regardless of the mapping options you've set, even if you aren't explicitly or implicitly allocating new memory. What I'd like, and what I think twic is asking for, is a way to "opt-out" of the overcommit paradigm at a process level, so that allocations by a given process reserve memory and may fail, but in return the kernel promises not to OOM kill it.

Re: Malloc Never Fails (2012)

#95
post #53

Earlier quoted context omitted.

Unless you need the address space, there is little gain with a 64 bit OS. The wider pointers use more RAM and eat up more of the available memory bandwidth and caches. So not swotching to 64 bits is likely the best use if the hardware.

It’s a toss up, I think: actual results depend on the task at hand. 64-bit has the benefit of more, wider registers, which can speed up certain tasks.

I stand corrected. I missed the fact that ARM also introduced new registers in AArch64. I thought that such a change only happened in amd64.

Re: Malloc Never Fails (2012)

#96
post #76
post #43

Earlier quoted context omitted.

Ig you try to allocate more than the system is willing to overcommit (e.g. a huge block all at once), malloc will fail. But if phyaical memory gets exhausted by accessing previously allocated pages, the OOM killer will evebtuslly come around and kill processes without signalling. Signal handlers could still make thenprocess (unknowingly) request more memory, so there is 0 guarantee that a handler could even run succe…

Oh yeah, I didn't think of that. I wonder if you could write a signal handler carefully to not allocate any memory, stack or otherwise, or is some return address or an internal structure being allocated transparently...

Just trying to allocate stack space for the signal handler may cause the stack to spill into a new page. That is absolutely out of anybody's control. And if that new page cannot be provided, it's game over.

Re: Malloc Never Fails (2012)

#97
post #70

Earlier quoted context omitted.

Thank you for your reply but I still don't buy it. As far as the program is concerned it is returned a memory block, what this "memory" is effectively behind the scenes is none of the standard's business. As long as the implementation manages to maintain the illusion it's perfectly fine AFAIK. The problem is when this breaks down and the kernel realizes that it can no longer maintain the masquerade. If at this point…

> If, when dereferenced, the kernel issues an order to Amazon for more RAM and waits for it to be installed to resume the execution, that's none of the C standard's business. We're not, and we never were, debating the situation where dereferencing the non-null pointer returned by malloc succeeds but takes long time due to your Amazon order. We've been talking about the situation where it fails . malloc is not allowed…

That is my point, it doesn't fail. Either the kernel finds out a way to map the memory and it succeeds, or it kill the program and the instruction never runs. Code that doesn't run can't violate the standard. When the code is allowed to run all the invariants are guaranteed to be respected. If I write this code:

    char *b = malloc(2);
    if (b == NULL) {
      return 0;
    }
    
    b[0] = 'A';
    b[1] = '\0';
    
    printf("%s\n", b);
    
    free(b);
The standard tells me that if the malloc succeeds then the following code, if allowed to run, will display "A" on stdout. The C standard cannot and does not guarantee that a C program can't be interrupted however. For the sake of the argument we could imagine a kernel that instead of killing the program freezes it indefinitely on disk waiting for RAM to be available. It's functionally the same thing. As long as the kernel doesn't let code run with broken invariants it's fine. This is completely outside of the scope of a language standard to define.

Or, to try one last time from a different direction, if you consider that the C standard mandates that accessing memory returned successfully by malloc has to be successful and I happen to press ^C when that happens in a program, should the kernel refuse to kill the program? This is obviously absurd, but it's effectively the same thing: the kernel reacts to some external state and decides to terminate the program.

Re: Malloc Never Fails (2012)

#98

Earlier quoted context omitted.

There is some support for this actually. Namely, when overcommit_memory is set to its default value (0), then it actually implements a heuristic for overcommit. (Where as the value `1` corresponds to "always overcommit.") Namely, only when overcommit_memory is set to 0, if you allocate memory with mmap and pass the MAP_NORESERVE option, then allocation behaves as if overcommit is always enabled and there is no check.…

The OOM killer can strike at any time, regardless of the mapping options you've set, even if you aren't explicitly or implicitly allocating new memory. What I'd like, and what I think twic is asking for, is a way to "opt-out" of the overcommit paradigm at a process level, so that allocations by a given process reserve memory and may fail, but in return the kernel promises not to OOM kill it.

Most of my programming experience is in Windows. Can someone briefly explain why it doesn't seem to need an OOM killer? Is it happier to page? Or it always commits on allocation? Or something else.

Re: Malloc Never Fails (2012)

#99

Earlier quoted context omitted.

The OOM killer can strike at any time, regardless of the mapping options you've set, even if you aren't explicitly or implicitly allocating new memory. What I'd like, and what I think twic is asking for, is a way to "opt-out" of the overcommit paradigm at a process level, so that allocations by a given process reserve memory and may fail, but in return the kernel promises not to OOM kill it.

Most of my programming experience is in Windows. Can someone briefly explain why it doesn't seem to need an OOM killer? Is it happier to page? Or it always commits on allocation? Or something else.

Windows does not have fork(), which as a sibling comment indicates is one of the main issues with removing overcommit.

Re: Malloc Never Fails (2012)

#100
post #95

Earlier quoted context omitted.

It’s a toss up, I think: actual results depend on the task at hand. 64-bit has the benefit of more, wider registers, which can speed up certain tasks.

I stand corrected. I missed the fact that ARM also introduced new registers in AArch64. I thought that such a change only happened in amd64.

The new registers in AArch64 aren't as useful as on AMD64 because ARM wasn't as register-starved as x86 to begin with.
Post reply on HN