The lost malloc()
158 points by matt_d a day ago | 75 comments
  • paaloeye a day ago |
    Never seen a 4 points story on the front page.
    • meerita a day ago |
      These are the misteries of HN.
      • paaloeye a day ago |
        I thought it was a mid-term election mystery
        • yorwba a day ago |
          Maybe the midterms caused you to refresh the front page more often so that you noticed this post before it had been there long enough to get upvoted a lot. (The minimum to get on the front page is 2 upvotes.)
          • paaloeye a day ago |
            Not really, it was "sponsored" by HN very early.

            Ref: https://news.social-protocols.org/stats?id=50362466

            • yorwba a day ago |
              According to your ref, it entered the front page at a "Top" rank of 8 at 8:10:00Z, when it had 2 upvotes. Just as I told you. (Did you confuse the "New" rank for the front page?)
              • paaloeye a day ago |
                No, look at the "raw" rank. It's the one without HN/manual intervention.

                It was catapulted to 8th rank while its "raw" was around 50th give or take.

  • jdw64 a day ago |
    When I was a college student (15 years ago), I first encountered C through A Book on C, and C seems like a language that is simple but can really do a lot. Looking at how old this language is, and how many concepts already used in modern languages were tried during its development history, is surprising. It's surprising that the concepts I thought were modern techniques today were already being tried decades ago—that is, before I was even born.

    It's amazing that a method like the Bump Allocator was already tried.

    How were the senior programmers able to do all of this? I'm just amazed.

    • trashb a day ago |

        > How were the senior programmers able to do all of this? I'm just amazed.
      
      I think it has to do with a combination of factors that changed over the years. First of all computer science was viewed more theoretical and less applied at that time. A computer scientist would be interested in optimizing a certain algorithm instead of making an app.

      Secondly the systems in that time where less complex meaning it was easier to understand and experiment with fundamental parts of the computer.

      Lastly at that time "programming" was closer to the metal so a average computer scientist at that time would likely have more knowledge of the deep internals compared to an average programmer today.

        > C seems like a language that is simple but can really do a lot
      
      I like to borrow a phrase from the realm of gaming: "easy to learn hard to master".
      • ahoka a day ago |
        I have always thought about C being a language with "simple" syntax (but things like type declarations are hell), but very complicated semantics.
        • 1718627440 a day ago |
          I think one of the issue in C is that some semantics do not have a syntax, you simply are required to write the code according to it. For example values/objects actually do have a type (effective type) and that is fundamentally what is deciding whether your access is UB. But you never declare that, you simply need to use the right type on access. Or there are ownership semantics in C, every usable interface description describes them in prose. If it's not defined, you are almost guaranteed to invoke UB. That's why I get a bit annoyed if Rust fanboys act like they own the concept of ownership, no it exists in C as well, but C does have different ownership semantics.
    • saidnooneever a day ago |
      if you write your program first with pencil and paper u'll be amazed at what you can do yourself.

      most people open an ide and start coding, or write some basic diagrams to get an overview/mental model. Back in the day any bitnlarge program would take hours to compile so really u did not want to have any bug or typo just to sit for hours until a compile error or logic mistake. Take it even further back to days before C and that is even more needed.

      a lot of high level modern languages seem to alleviate that need, likely so that enterprise software can be written a bit faster because the features need to arrive faster.

      still in more modern languages i'd recommend starting with pencil and paper, write most of it if not the whole thing out. u'll find much nicer patterns and will save yourself a bunch of refactoring. even for small programs.

      • lieks a day ago |
        When I was at school, I used to program on paper like this (due to not having a computer during class). It was accidentally a great exercise, that I think everyone should try. Because of it, I find myself writing mostly bug-free code on my first try these days (my bugs tend to happen on interactions between parts of a system I designed separately).
        • 1718627440 a day ago |
          I had the same experience of writing almost no bugs when writing on paper. (Only conceptual bugs, e.g. in architecture or that I solve the wrong problem in the first place.) But when I now write code on a computer, I do introduce bugs. However I regularly find tricky and rare to occur race conditions or heisenbugs just by printing and reading the code from top to bottom, without a goal, just for entertainment. I did not know of the existence of the bug, before I find them. They stick out when you read it, because it's not what you have in your head that should be written there.

          It helps me to print it in a different font/color and without syntax highlighting to force my brain to read it as new code, instead of simply assuming it's the same as I already know.

          • saidnooneever 16 hours ago |
            i recognise this. i do pen and paper still but i do also write bugs. when i do i try to make test programs to learn why, and ideally recognise where my pen and paper whent wrong, because those are gaps in my real understanding of how my language, the program or interactions with its environment and platform really work. Needless to say i always find myself having lots to learn still :). i think in reality only once or twice i wrote a program truly free of bugs. relatively trivial programs ofc (simple socket client/server with basic binary protocol or so. easy to reason about, no complex sync or threading requirements).

            i never use syntax highlighting. one day someone told me it was very distracting, i turned it off and suddenly things were calm. Maybe its just taste but i do find it helpful. you really read stuff rather than assuming some color happening means its correct or incorrect subconsciously

    • Anon4Now a day ago |
      > It's amazing that a method like the Bump Allocator was already tried.

      The old saying "Necessity is the mother of invention" applies. Smart people + system constraints => ingenuity.

    • bregma a day ago |
      The answer is more likely that modern students just don't learn their history and think they've cleverly come up with something new (after all, it's new to them). If you've learned your history you would understand it has ever been thus. Aristotle and Hesiod complained about it, and Aristophanes even wrote a play satirizing it that could be performed today and it would still be relevant.
      • 1718627440 a day ago |
        Why do they go to university then? The entire point of an university is to get taught the fundamentals and be able to derive current (and thus future) knowledge yourself. If you simply want to learn the current state of a craft, that's what vocational schools are for.
        • wahern 20 hours ago |
          University provides you the opportunity to research and understand the history. You don't need university for that, but the time, people, and resources available to you make it much easier.

          But it's voluntary. Actually course curricula basically just drop hints at the history as part of a short perfunctory narrative. Along with the deeper conceptual instruction (framed according to the then-current beliefs), that's better than vocational instruction, but definitely falls short of the idealized liberal education. Ideally you survey the entire historical progression of a field, like St John's College does where, e.g., you start learning geometry by reading Pythagoras, or calculus by reading Newton, and then having vigorous discussion to suss how how thinking changed or didn't change between eras and how that might inform today's thinking. Not sure how much marginal benefit is had by going all-in like that, though, as a practical matter, except for very serious students.

          • 1718627440 16 hours ago |
            Of course there is always a depth below, which to explore is entirely voluntary. But university courses don't train you directly on the layer you are going to solve the actual problems on your job, they test always at least on layer deeper and then maybe test for one specific algorithm/approach/problem as an example.

            > you start learning geometry by reading Pythagoras, or calculus by reading Newton

            You can do that, if you actually care about the history of mathematics, but normally it's enough if someone introduces you to a combined theory of e.g. Pythagoras and Newton.

            So in a way you are saying, university is often not actually teaching temporal genesis, which I agree with, but my point is that it does teach causal genesis, with citations on the temporal aspect.

    • momocowcow a day ago |
      They came up with bump allocators because they had a blank mind, devoid of today's complexity. You would also come up with it if you were sat in front of a terminal with no internet. Ask anyone old enough.
  • veltas a day ago |
    I don't associate with the author that well here because I'm not hyped about 'arena allocators' and I don't really care that free doesn't receive a size. I think the interface was okay.

    Also 'arena allocators' (this meant something different like 20 years ago so I think the name just got rebranded) are not that good, they make some things easier and improve performance sometimes, they also are liable to use more memory and cause more fragmentation if not used with care. That is one of the many reasons why we slowly evolved away from the old linear allocators, but also because we just wanted a simple and flexible interface to hide complexity.

    • warmwaffles a day ago |
      Arena/linear allocators have their place. In real-time systems they are fantastic to reset quickly and bypass having to interact with the kernel.
  • OskarS a day ago |
    > Not only that, mfree() receives the size of the object it is deallocating, as it should.

    I've always thought that one of the biggest tiny mistakes in the history of this industry. It means, more or less, that you're forcing the memory allocator to keep track of these sizes when it shouldn't have to. There's virtually no sensible case where the person calling free() doesn't know the size of the allocation, so now we're keeping that book-keeping twice, in "user-space" and inside the memory allocator. Like, think about the cases when you'd call malloc:

    * For allocating a single object of type T, the size is just `sizeof(T)`, so you can just pass that to free()

    * For allocating an array of objects, the size is `count * sizeof(T)`, and I can't think of a single time where you DON'T know what `count` is. It's either statically sized (in which case it's just a constant), or if you have a dynamically growing array, you need to keep track of the reserved space to know when you reallocate. If nothing else, you need it for bounds-checking.

    * For chunks of raw memory, you also presumably know when deallocating what the size of the raw memory you allocated is, for the same reasons as the previous point. Like, just having a raw char* pointer lying around with no size information is just terrible C practice.

    If you truly don't know the size of your allocation (very hard to imagine when this would ever happen), you should be forced on the user-side to keep track of it somehow, not delegate that to the allocator.

    It's a tiny amount of overhead, but it's for EVERY SINGLE MEMORY ALLOCATION since like 1975. Imagine how many times malloc() and free() has called since then! How much electricity, CPU usage, and memory has been wasted! It boggles the mind!

    • 0xdeafbeef a day ago |
      "void*" sadly exists, and there are a lot of edge cases.

      I tried using TCMalloc with rustc, and it segfaulted. Rust knows the sizes of its allocations, but things can still go wrong at the allocator boundary.

      Size should be an optimization hint, not a correctness requirement. Otherwise, it's just another security pitfall

      • OskarS a day ago |
        I don't agree. Zig allocators require the size of the allocation (technically they take a slice, but a slice is ptr + size), as does the C++ polymorphic allocator, as does many allocator interfaces in many libraries (see for instance the allocator interface in Lua, my personal favorite C interface for memory allocation [0]). Clearly having it as a correctness requirement works just fine.

        [0]: https://www.lua.org/manual/5.4/manual.html#lua_Alloc

      • SkiFire13 a day ago |
        > "void*" sadly exists

        But _somewhere_ you need to know what it represents, otherwise it's useless.

        > I tried using TCMalloc with rustc, and it segfaulted. Rust knows the sizes of its allocations, but things can still go wrong at the allocator boundary.

        Things can go wrong, doesn't mean they will go wrong due to the reasons you're thinking of.

    • StilesCrisis a day ago |
      Don't worry, the allocator almost never dedicates actual heap space towards storing your allocation sizes. Instead, allocations get bucketed by size, and you can derive the size by working out which bucket the allocation is in. This is cheap and the bucketing is a good strategy anyway.
      • senderista 21 hours ago |
        Unfortunately, "boundary tags" containing allocation size are still pretty common in dlmalloc-derived implementations like glibc, although slab allocators like you described are the preferred approach for most new implementations.
    • mpyne a day ago |
      > There's virtually no sensible case where the person calling free() doesn't know the size of the allocation

      We already have enough memory-unsafety bugs going around without making free() more difficult to use correctly as well.

    • fasterik a day ago |
      I think this is missing the forest for the trees. The potential savings of one extra size_t per allocation are miniscule compared to the overhead of using malloc() in the first place, with a potential syscall on every allocation. If you care about waste, you should ask for those pages from the OS directly, once at init, and use arenas.
      • OskarS a day ago |
        If you think you can convince the entire computer industry to stop using malloc(), I wish you the best of luck. In actuality, your computer likely calls malloc() somewhere thousands of times per second in low use, probably millions of times during intensive use. Wouldn't it be nice if all those calls were just a bit less resource intensive?
        • fasterik a day ago |
          I'm curious, what do you expect the performance improvement to be, in terms of CPU cycles per allocation? malloc() costs on the order of 10,000 cycles on the slow path.
          • OskarS a day ago |
            I don't know what the exact impact would be, but it's certainly not zero, and multiplied by every malloc, it adds up. My point is mostly that the API for malloc()/free() is designed in such a way to both limit the kind of implementations you can make for it, and make most implementations a tiny bit slower than they need to be.

            BTW, when malloc() takes 10,000 cycles, you've either hit some weird edge case in an allocator or (much more likely) malloc() has run out pages it can use to hand over to the application and has to ask the kernel for more memory. I measured malloc() for a recent change in one of our products, and in my test the median time was less than 100ns. malloc() is usually very fast. But with a better API, it could be faster. Multiplied by every memory allocation on every computer in the world (more or less) for the last half-century, it's becomes a very big number.

      • 0c3ca83 a day ago |
        There's no syscall on every allocation. With many allocators, the common case is popping a node off a linked list.
        • fasterik a day ago |
          That's why I put the word "potential" in there. Every allocation potentially needs to go to the OS for more pages.
          • 0c3ca83 a day ago |
            And every memory access potentially enters the kernel via a page fault.
          • cowlevel 12 hours ago |
            Any given CPU instruction potentially isn't in cache.

            And yet, they can't all not be in cache. As soon as the cache is accessed for one instruction, a bunch more are pulled in too.

            Any given vector.push call could reallocate the vector, but it's amortized O(1).

    • dragontamer a day ago |
      > There's virtually no sensible case where the person calling free() doesn't know the size of the allocation

      Polymorphism in C++?

      A* blah = new B();

      • 1718627440 a day ago |
        You already need a virtual destructor here anyway, because it needs to know about the actual type B, which includes it's size.
        • dragontamer a day ago |
          In C++, the destructor doesn't call free() because the destructor doesn't know if it's on the stack or heap.

          Consider:

              void f(){
                  A* tmp = someFunction(stuff);
                  foo(tmp);
                  delete tmp;
              }
          
              void g(){
                  A tmp; // destructor will be called, but no free/delete
              }
          
          What is the size of A? Answer: you never know in C++ due to polymorphism. It might be a B or other subclass. It is truly a variable length operation.

          And secondly, the destructor cannot tell if it's f() or g()

          • adev_ 21 hours ago |
            > What is the size of A? Answer: you never know in C++ due to polymorphism. It might be a B or other subclass. It is truly a variable length operation.

            You could easily go around it.

            The compiler knows when creating the destructor for B.

            In your example, to have correct C++, you need to have declared a virtual destruct-or for B. You could encode the size of B in a static offset from the virtual destructor or simply as a return value from it.

            This is not how it is done now, mainly because how free was designed in C.

            free() design is a terrible mistake. Probably one of the worst design mistake of C with the null terminated / no-length specified string and the preprocessor.

          • dgrunwald 21 hours ago |
            But it's possible for `delete tmp;` to call a user-defined `operator delete()` in the derived class! https://godbolt.org/z/hvePa6jMP

            The way this works under the hood is that every polymorphic class has two destructors (so two destructor entries in the vtable): the "complete object destructor" is the ~A() you know from C++, and then there's also the "deleting destructor" which combines ~A() + delete.

            So the deleting destructor can call free() while knowing the derived object size, even for a delete-via-base-class-pointer.

          • cowlevel 12 hours ago |
            At least in the MSVC implementation, "delete tmp;" calls "operator delete" polymorphically, through a hidden virtual function. I think this is because derived classes may override "operator delete"?
    • adrian_b a day ago |
      Many allocators must keep 2 sizes for every allocated object: the size of the allocated memory and the size actually occupied by the requested object.

      Some allocators keep other extra information for each object. Thus they need all that information and if the "memory free" function gives them only the size of the object, that is not enough.

      Since the size is not enough, it is superfluous for the user program to provide it. When given a pointer to an object, the memory allocator will know where to find all the associated data. It might be in the cache line that is immediately before the pointed memory, or it might be in an array, at an index that can be deduced somehow from the value of the pointer, or all the information might be implicit, e.g. when objects are allocated from stacks of objects of the same size, when the size can be deduced from the pointer value, so it is not stored anywhere.

      Therefore the correct definition for a memory free function is to have only a pointer as parameter, to give freedom to the allocator to use whichever strategy is deemed better.

      • OskarS a day ago |
        > Many allocators must keep 2 sizes for every allocated object

        And wouldn't it be nice to just make them keep one number! That's a size_t and a couple of cycles saved for every malloc()!

        I will say, this is not some far-out niche idea of mine, it's basically universal for all "new" implementations of memory allocators to require exactly this information for deallocation. There's a reason Zig allocators take a slice and not a pointer [0], why std::pmr::polymorphic_allocator::deallocate takes a size [1] and why Rust allocators require it as well (in the layout param) [2]. It's just a better API design.

        EDIT: for C++, the better reference is the Allocator named requirement, which the polymorphic allocator is just one example of. But you can see it there as well in the deallocate() method [3]

        [0]: https://ziglang.org/documentation/master/std/#std.mem.Alloca...

        [1]: https://en.cppreference.com/cpp/memory/polymorphic_allocator...

        [2]: https://doc.rust-lang.org/std/alloc/trait.GlobalAlloc.html#t...

        [3]: https://en.cppreference.com/cpp/named_req/Allocator

        • Sesse__ 20 hours ago |
          > And wouldn't it be nice to just make them keep one number! That's a size_t and a couple of cycles saved for every malloc()!

          You can make them keep basically zero numbers per allocation; most modern mallocs use size classes, and can pack objects of the same size class tightly with no metadata inbetween. (You still need some numbers per page/span and such.)

      • senderista 21 hours ago |
        But sized deallocation gives the allocator implementation more freedom to optimize, not less. More information from clients = more optimization opportunities for the implementation. I don't understand how you can claim the opposite is true.

        Source: I have implemented allocators.

        • mrheosuper 11 hours ago |
          I don't see the point

          If sized parameter helps optimization, why allocator just not put it in the header block already ?

      • Veserv 20 hours ago |
        No, having the size would be immensely useful. Consider the standard allocator design.

        You have a fixed number of small-size block allocators (say 8-256 bytes) and then a sequence of exponentially-sized large block allocators.

        For small-size block allocators you want limited allocator overhead, limited over-allocation, high speed, and likely the ability to support certain alignments like 8, 16, and 64 (cache line). Attaching a requested size and actual size (or even just one) to every block would be tremendous overhead.

        For large blocks you care less about allocator overhead and over-allocation since it is less overhead as a percentage. So, attaching requested size and actual size to every block is a small cost. However, you likely also want the ability to support certain alignments like 4K, 16K, 2MB, etc. (natural hardware or OS sizes).

        So, you generally want two distinct strategys and bookkeeping mechanisms based on the size of the allocation. If deallocation does not take the requested size, then your very first problem is figuring out which mechanism you are using. The problem with this is that you want small-size allocations to have small overhead, so the discrimination mechanism must also be small-overhead.

        If you pass in the requested size, then it becomes trivial to distinguish with zero allocator overhead. Is it less than 256 bytes (or whatever small size you choose)? Cool, it is small-size. Round up to the nearest small-size block. Release the memory to the identified small-size block allocator. This has zero per-block overhead, is totally trivial, extremely fast, and preserves alignment.

        If the allocated size is in the large-block regime, then you know you can use a per-block overhead scheme. Except, this is still better. If you do not know the requested block size, then you are limited to either a header at negative offset or a auxiliary data structure keyed on the pointer value to determine the actual size. The former messes with your alignments and the latter requires the allocator to be stealing unrelated memory for its own data structures. If deallocation tells you the requested size, then you can easily use a footer scheme instead. Just always over-allocate enough space for a footer and then you can always just jump forward by the requested block size to find the footer and you do not mess up your alignments.

        Getting the requested size, which the caller is basically always already remembering via type information, gives you a lot of advantages and optimization levers.

    • im3w1l a day ago |
      It's tricky. The harder you make it to use the lower layers the more people will say fuck it and use a higher layer. How many people decided move to java or even script languages because they were scared of undefined behavior security issues?

      That's not a 10% overhead, java is like 2x, and a script language could be even 100x.

    • jimis 20 hours ago |
      Indeed, this baffled me since moving from Pascal to C. In Pascal you could use getmem()/freemem(), both accepting the size of the object. As a result the allocator should be simpler and more performant. In C the allocator has to track that size, in addition to your program tracking it separately. And the complexity of allocators in C can go into black-arts territory.
    • JoeAltmaier 19 hours ago |
      In any abstract allocation, it is entirely possible that the place the object is freed has little knowledge of how it was created. This is object abstraction at it's basic definition.

      I don't do that; I like to have the allocation and free in the same code module so I can ensure there's no leak, double deletion, null deletion etc. But I know it happens, routinely. In a library for instance.

    • mkehrt 18 hours ago |
      This is just 100% wrong. The API should be designed to prevent mistakes. You're arguing in favor have having more memory safety bugs.
      • cowlevel 12 hours ago |
        That isn't the C and C++ philosophy, especially now that if you want to use Rust, you can just use Rust.
    • wahern 18 hours ago |
      C2y has already added free_sized, FWIW, which is symmetrical with malloc. See 7.25.4.7 in the latest draft at https://www.open-std.org/jtc1/sc22/wg14/www/docs/n3998.pdf

      It also adds free_aligned_sized as the counterpart to C11's aligned_alloc. Though while you can pass memory from aligned_alloc to free, you can't use free_sized or free_aligned_sized with aligned_alloc'd or malloc'd memory respectively, a potential (and unavoidable?) foot gun.

      • dooglius 18 hours ago |
        But if you still have to support the plain free functions it doesn't help because you'd still have to track the information anyway.
        • wahern 17 hours ago |
          The degree to which it helps or not depends on the implementation. For example, free could be a slow path that does extra bookkeeping lookups the sized variants wouldn't need to. Large allocations and non-default aligned allocations often use different bookkeeping data structures from how most allocations are handled internally anyhow. In such cases that check needs to be done up front, and at least on virtual memory systems (where it's relatively easy to segregate allocations types by VM range) it doesn't much matter whether you're indexing that first level directory based on pointer or size.

          But, yeah, it's not an ideal situation from the perspective of free_aligned advocates.

        • 1718627440 16 hours ago |
          At load time, you do know whether a program is going to use plain free, so you can select the implementation then.
    • dark-star 17 hours ago |
      > you're forcing the memory allocator to keep track of these sizes when it shouldn't have to

      Sounds much safer to me than have every single developer, program or library keep track of those sizes properly... I mean that way it's at least only done in 1 place and done correctly, instead of forcing every developer to suddenly keep track of yet another value

    • teo_zero 13 hours ago |
      > I can't think of a single time where you DON'T know what `count` is

      A string created by strdup().

      • cowlevel 12 hours ago |
        Then you know it's strlen+1
        • teo_zero 8 hours ago |
          So you don't know it: you must calculate it, via an expensive strlen().
          • NekkoDroid 5 hours ago |
            To be fair, that is a downstream effect of C's worst mistake (NUL terminated strings). Also, if every allocation you'd get is ptr+size you could just derive it by also copying the size.

            Basically, the issue is C having unsized allocations and related not tracking string length.

  • fjfaase a day ago |
    The sbrk system call in linux is still available to get more heap from the operating system. So, memory is still allocated in a linear fasion and never released again. Maybe now functions like mmap change this. I used sbrk to implement malloc for a very limited standard libary implementation.
    • cowlevel 12 hours ago |
      sbrk has been obsolete for almost three decades. mmap is almost always the way memory is allocated from the kernel.
  • adrian_b a day ago |
    The author did not really find from where SIMULA 67 had taken "new".

    In November 1965, C.A.R. Hoare published an extremely influential paper: "Record Handling". This was a proposed extension for the successor of ALGOL 60.

    Almost all of the features that were added in SIMULA 67 over its predecessor, the SIMULA language, come directly from the paper of Hoare, with two big exceptions: class inheritance and the "virtual" procedures, which were invented by the SIMULA 67 creators (Kristen Nygaard & Ole-Johan Dahl) and which are essential for object-oriented programming.

    The SIMULA 67 keywords "class" and "new" were taken from Hoare's paper (Hoare actually had taken "class" from COBOL 60, which used a very different terminology in comparison with ALGOL 60, among the many differences being the use of "class" instead of the "type" used by ALGOL 60).

    Hoare's paper discussed a lot of programming language features, most of which were new, including defining structured types with constructors and destructors, discriminated unions (taken from John McCarthy), enumerations, the NULL pointer and many others.

    SIMULA 67 was one of the first languages which implemented many of the features proposed by Hoare. Other languages that implemented some of the proposed features were IBM PL/I, ALGOL 68, then a couple of years later, in 1970-11, Pascal.

    The keyword "new" had already been used for the first time by Niklaus Wirth, but at Wirth it had a different meaning than at Hoare. It declared a variable that was local to a block, which would hide any old variable with the same name that had been declared outside that block. So "new" at Wirth was equivalent with "auto" and "register" of the language C.

    Later, in the language Pascal, Wirth abandoned his original use of "new", replacing it with the "new" introduced by Hoare.

  • mac3n a day ago |
    isn't `arena` just a typo for `area`?
    • ajasmin 18 hours ago |
      No. Arena really is what a pool allocatable memory is called.

      The article claims the term first appear in V6 Unix though I couldn't tell you why it's called that.

      It does help prevent confusion, though, a memory "arena" and a memory "area" don't both mean the same thing.

      • cowlevel 12 hours ago |
        I'd propose "colosseum" for a really big arena such as one used by a compacting GC, and "skyrim" for a scrollback buffer (holds elderly scroll-text), but they'd never catch on.
  • tptacek 19 hours ago |
    Malloc implementations are anything but boring!

    https://csapp.cs.cmu.edu/3e/docs/dsa.pdf

    • Mikhail_Edoshin 16 hours ago |
      Malloc itself is not boring. What is boring and distracting is the need to think about managing memory when doing something else. (And we normally do something else.) Here the memory management part must be reduced to a mere technicality, some standard prologue/epilogue. It's not yet there, I think.
      • cowlevel 12 hours ago |
        GC languages do exactly that.
        • Mikhail_Edoshin 8 hours ago |
          True. But GC takes too much control. Using Pythons as an example, first all is well, but then you need to turn it off selectively and have to learn first the whole concept of (reference-counting) GC and then augment it with a new concept of weak references. (Which are not just objects without GC, they are objects with more complex GC routines.)

          A thing appears simple when it allows you to make distinctions you care about and avoid making distinctions you do not care about. C is weak with the latter, but Python with the former.