$ cat bigbuf.c
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define DEFINITELY_BIG_ENOUGH 2U*1024*1024*1024
int main(int nargs, char ** args)
{
char * definitely_big_enough = malloc(DEFINITELY_BIG_ENOUGH);
if (nargs > 1)
{
memset(definitely_big_enough,0, DEFINITELY_BIG_ENOUGH);
}
sprintf(definitely_big_enough,"%s",args[0]);
return 0;
}
$ /usr/bin/time ./bigbuf
0.00user 0.00system 0:00.00elapsed 100%CPU (0avgtext+0avgdata 1356maxresident)k
0inputs+0outputs (0major+80minor)pagefaults 0swaps
$ /usr/bin/time ./bigbuf 1
0.05user 1.25system 0:01.31elapsed 99%CPU (0avgtext+0avgdata 2098468maxresident)k
0inputs+0outputs (0major+524369minor)pagefaults 0swaps
YMMV on different operating systems. Of course this is a program only an idiot would write, but things like caches are often significantly bigger than the median case, especially on Linux where you know there is overcommit.People should really read more on safety semantics in Rust before making comments like this, it's quite annoying to bump into surface level misunderstandings everytime Rust is mentioned somewhere.
Safe abstractions are created out of unsafe operations by making sure it's impossible to violate the operations' preconditions. Either by checking at runtime and returning an error or aborting the program if they're violated, or by using the type system and borrow checker to verify them at compile time (writing the code such that any program that could violate the preconditions must have a type error.)
If Rust didn't have unsafe, the only way to access the underlying unsafe operations would be dropping down to C/C++/Assembly, or hardcoding them in the compiler. This is what other languages do, and it's ergonomically worse because the barrier to adding a whole new language and build system to your project is quite high.