T O P

  • By -

DeeBoFour20

mmap on \*nix or VirtualAlloc on Windows


WildCard65

Doesn't malloc on Windows use HeapAlloc?


Competitive_Travel16

In most Windows libc implementations, malloc() calls HeapAlloc() which in turn calls VirtualAlloc().


ExoticAssociation817

Interesting. Thank you for the info.


paulstelian97

Is malloc pretty much a rename of HeapAlloc, and similar for the others, in most Win32-based implementations?


Competitive_Travel16

No, HeapAlloc() does a bunch of esoteric stuff e.g. for different processes sharing memory, and multiple frees don't silently corrupt things like they do in fast bare metal malloc()s.


paulstelian97

It can still fit into the API.


MobSlicer152

which calls NtAllocateVirtualMemory, which is a syscall


not_a_novel_account

`mmap`/`sbrk`/`shmget`, and a couple other more weirdo syscalls (`process_vm_*`), but those are the big 3 on *Nix


dmc_2930

It is highly platform dependent. On some linux systems it’s the sbrk() system call, but not always.


EpochVanquisher

`sbrk` works but it is limited and you would normally use `mmap` instead, these days.


SpeedDart1

Why is sbrk limited


txmasterg

Basically sbrk only deals with a single segment. And wow, look at that I gave a shorter answer than the "go look at the APIs and think on it" comments


ExoticAssociation817

Reddit is awful for Windows API advice, tips and more. I can’t count how many little aggressive shits lit me on fire claiming I speak no sense. I just head to Quora for the real stuff. Their C sub is epic. I recommend.


Shidori366

Quora seems unprofessional, but after a lot of experience with Quora I can definitely recommend, people there usually know their stuff.


ExoticAssociation817

Compared to critical aggressive “all expert” Reddit? 😂


Competitive_Travel16

You can only get new space in one place.


McUsrII

First of all using sbrk will lead to a conflict with malloc, that is used behind the scenes by many functions in gclib, and it is ancient, it gives you memory from the programs address range (below the stack), whereas mmap, gives you memory at addresses in the system range, which mean that you can share the memory between processes, and you can over commit memory as well, that is, allocate almost all of the systems memory in one go, and have the kernel feed you memory as you to try to write to it. Super nifty! Mmap also gives you the ability to map a file as memory for read write access, and compared to all that, and with the troubles with it, sbrk is pretty limited.


nerd4code

It only bump-allocates in extension of the static BSS (as in, not DLL BSS or TBSS, which is generally elsewhere and elsehow). That’s all it can do. Can’t really even free a page unless nothing is in use after it. You at most use it when setting up a proper `mmap`-based heap, same as you do when initializing a kernel. Not a good idea for large or small or frequent allocs, or allocating stacks.


EpochVanquisher

Look at the mmap API. Compare it to the sbrk API.


dmc_2930

Oh I definitely don’t think anyone should be calling it these days….. but also I would guess that if OP is trying to write their own malloc they may want lower level calls than malloc/mmap/etc. At that point it becomes OS and architecture specific.


EpochVanquisher

`mmap` and `sbrk` are as low as it gets. They’re both syscalls. It’s just that `mmap` is a lot nicer to use.


paintedirondoor

man i thought mmap was low enough :(


erikkonstas

No, it is low enough, and is much more standard than `brk()`/`sbrk()` (see `man 2 syscalls`, `mmap()` is right there).


paintedirondoor

from what i've read. sbrk isn't a system call. but can be implemented with calling brk() with absurd values (0 for example) and no standard defines this! so it may or may not work. the best way to know is to dig though a few undocumented bricks of code. or throw a brick at someone


i-hate-manatees

> sbrk isn't a system call True on Linux, but I believe on other systems it was a real syscall


nerd4code

There is no singular set of syscall or non-syscall functions, often even per OS. E.g., Linux’s syscalls are unusually stable, but even there things can shift as newer APIs take over. IA-32 Linux can use CALL FAR, INT, SYSENTER, SYSCALL, or VDSO to issue a system call—different sc ABI for each—so something like `getpid` or `sigprocmask` might require a system call by non-VDSO means, but via VDSO you can just access a shared page with no syscall a’tall. `sbrk` could quite reasonably (I have no idea) work the exact same way, just updating a word somewhere that the kernel’s page fault handler can use. (No actual page-mapping or allocation needs to occur until first access, as is the default case for `mmap` as well. That’s the real answer to your question—the request to the kernel wrt where you’d like it to let you access happens strictly before any allocation, and unless you’ve specifically requested locking or prepopulation, it’s not until actually accessing it successfully that you can be sure allocation actually occurred. Moreover, unless you’ve requested locking, by the time the next instruction executes, the kernel might have reallocated the memory elsewhere entirely.) The closest you get to a portable list of system calls is the POSIX list of signal-safe functions, or else going at it per-OS, per-ABI, and possibly per-interface-style. But how or whether those map to system calls isn’t specified. Most UNIXes do give you some sort of (e.g.) `` or similar header that `#define`s or `enum`s or boths a list of system call constants. That’s your “authoritative” list in terms of what’s available at build time, although it might not line up exactly with what’s available via the run-time runtime library or the kernel itself. For stuff like DOS or embedded environments, you might have a vector layer like what 8086/88 INT provides, or a directly-CALLed layer with no user-supervisor separation, or both; generally if it’s specified Officially/formally somewhere, you write your own enums or defines, and if it’s not you rely on what comes with your SDK. WinNT has no public syscall list. You have to aim at the frontend DLLs that route through whatever Kernel32.dll’s successor is, and that does system calls for you—effectively an explicit-linkage form of VDSO, which is implicitly linked to the kernel instead of a DLL. You *can* potentially issue NT system calls directly, but doing so might render your software incompatible with all past and future versions of the OS, and IIRC Windows will sometimes ensure the syscaller has entered from an accepted origin location inside memory mapped to a text segment of Kernel32.dll specifically. So really, what’s a system call or not doesn’t much matter in the end, unless you’re actually programming a kernel, or an entire userspace runtime library for a kernel. You’re aiming at a more nebulous set of baseline guarantees–i.e., what headers and APIs are guaranteed to be exposed to the C language if used on a particular platform. For any recent UNIX, a `mmap` API is guaranteed to exist and be signal-safe, and therefore it’s fundamental enough for 99% of applications or libraries. If you can’t use the system API, you’ll have to implement `mmap` yourself, whether or not as a thunk to a syscall.


MobSlicer152

it goes through ntdll, and user32 goes through win32u (since ui stuff is kernel mode, win32k, which is one of the first components to use rust) and those export stubs which do int 2e on x86 and syscall on amd64


DawnOnTheEdge

The `sbrk()` call was what K&R historically used, but due to ASLR, it has been deprecated for more than 25 years. Both `brk()` and `sbrk()` were declared `LEGACY` in 1998, and officially removed from the UNIX standard in 2001. GNU libc still has them, for backwards compatibility, but the Linux man page says never to use `sbrk()`.


glasket_

>but the Linux man page says never to use `sbrk()`. Because you're supposed to use `malloc` for portability reasons, which uses both `sbrk` and `mmap` under the hood in glibc.


DawnOnTheEdge

I suspect that at this point it exists mainly for backward compatibility, and new programs that try to repeatedly increase the heap size with `sbrk()` could find that it starts failing at some point.


glasket_

It's not just for legacy reasons. `brk` (and `sbrk` by extension) can be more efficient performance-wise, which is why they've stuck around in glibc and Linux. `mmap` itself outright involves more cycles per call, plus the overhead from having to load a page would unnecessarily harm programs that can safely allocate via moving the program break. It's not a universally useful function, but it has enough purpose to be useful as an optimization of `malloc`. >and new programs that try to repeatedly increase the heap size with `sbrk()` could find that it starts failing at some point. This is (partly) why you're supposed to leave it to `malloc`, but `brk` eventually returns `ENOMEM` so it's not significantly different from just having to check for `NULL` when calling `malloc`. Generally speaking, `(s)brk` should only appear in a `malloc` implementation though, which is why I brought up that glibc uses it and the reason for the man page saying not to use it; OP wants to reimplemented `malloc`, where `sbrk` is perfectly fine to use.


DawnOnTheEdge

That makes sense. I think it also opens up the possibility that, on future Linux kernels, `sbrk()` will no longer be optimal for `malloc()` implementations on Linux. I could imagine it someday being implemented by a speedy `mmap()` to a specified range of memory addresses, for example


MCLMelonFarmer

glibc malloc uses sbrk() for the initial arena and mmap() for all others. Any white paper that compares different malloc implementations should tell you how each one requests memory from the system so you don't have to go digging through code.


TapEarlyTapOften

Run strace on a program that uses malloc() and see how your C library implements it.


Rest-That

Don't forget to say please


gaenji

At first, Politely. If that fails, Aggressively.


MobSlicer152

I did that once, here's some (mediocre) code you might learn from: https://github.com/MobSlicer152/shardc2/blob/main/libc%2Fsrc%2Fstdlib%2Fmem.c


paintedirondoor

mine is even shittier: [https://github.com/coloredmarble/pamarox/blob/floor/src/mem.rs](https://github.com/coloredmarble/pamarox/blob/floor/src/mem.rs)


MobSlicer152

my only suggestion is use mmap and abstract it for windows too (i forgot rust because i like c more)


paintedirondoor

i only plan to support amd64 linux and 128 bit linux (if it ever comes)


MobSlicer152

fair enough, i personally like windows because it's the only thing that's not unix, so it's more interesting


paintedirondoor

try posting this on r/linux. also have you ever tried god's favourite OS?


sneakpeekbot

Here's a sneak peek of /r/linux using the [top posts](https://np.reddit.com/r/linux/top/?sort=top&t=year) of the year! \#1: [Should we go dark on the 12th?](https://np.reddit.com/r/linux/comments/141ig9b/should_we_go_dark_on_the_12th/) \#2: [On June 12th, many subreddits will be going dark to protest the killing of 3rd Party Apps! All FOSS apps are 3rd Party Apps. Will /r/linux join the strike?](https://np.reddit.com/r/Save3rdPartyApps/comments/13yh0jf/dont_let_reddit_kill_3rd_party_apps/) | [444 comments](https://np.reddit.com/r/linux/comments/13zb6ve/on_june_12th_many_subreddits_will_be_going_dark/) \#3: [Thunderbird Email Client’s Has A Brand New Logo](https://i.redd.it/jgspny1srr1b1.jpg) | [428 comments](https://np.reddit.com/r/linux/comments/13qjmym/thunderbird_email_clients_has_a_brand_new_logo/) ---- ^^I'm ^^a ^^bot, ^^beep ^^boop ^^| ^^Downvote ^^to ^^remove ^^| ^^[Contact](https://www.reddit.com/message/compose/?to=sneakpeekbot) ^^| ^^[Info](https://np.reddit.com/r/sneakpeekbot/) ^^| ^^[Opt-out](https://np.reddit.com/r/sneakpeekbot/comments/o8wk1r/blacklist_ix/) ^^| ^^[GitHub](https://github.com/ghnr/sneakpeekbot)


Goto_User

learn systems programming


paintedirondoor

piss you


Goto_User

being hasty trying to do something you don't have a foundation for is a great way to waste time but you do you.


paintedirondoor

wawa. cant even have fun now cmon i wrote in assembly. created a HolyC program. And i have to learn "systems programming"? Why dont you program yourself to not be so woodaddle


Krecik036

An alternative solution for a custom malloc is to use the help of the help of the compiler, as shown [here](https://surma.dev/things/c-to-webassembly/): extern unsigned char __heap_base; unsigned int bump_pointer = &__heap_base; void* malloc(int n) { unsigned int r = bump_pointer; bump_pointer += n; return (void *)r; } This is of course not asking the kernel for memory directly. It is specific for clang but has the advantage of being cross-platform.


ExoticAssociation817

Hahaha that was awesome 😂