HNHacker News
TopNewBestAskShowJobs

skitter

759 karma · joined February 5, 2020

submissionscomments
skitter··on Fixing for loops in Go 1.22
If you append to a slice, you can't rely on the changes showing up in the original slice, nor on them not showing up.
skitter··on So You Think You Know C? (2020) [pdf]
Something as simple as adding integers is tricky due to its implicitness. Due to promotion, the following code works on some platforms but is verboten on others:

    int16_t a = 20000;
    int16_t b = a + a;
But even ignoring size, it can bite you:

    unsigned int c = 1;
    signed int d = -2;
    if(c + d > 0)
      puts("1 + -2 > 0");
That code prints because of balancing: The signed value gets cast to an unsized int, which can't hold the value.

For not directly integer related semantics, creating an out-of-bounds pointer is UB, unless it points to one past the end of the object, in which case you can create the pointer but can't read from it. And if an object's lifetime has ended, pointers to it aren't valid anymore even if you don't even read from it:

    void *foo_1 = malloc(1);
    free(foo_1);
    void *foo_2 = malloc(1);
    printf("Checking for same allocatoin: %d", foo_1 == foo_2);
If you go by the standard, strictly speaking this is UB:

    #include <stdio.h>
    int main(void) {
        puts("Hello World);
    }
But don't worry, real compilers will refuse to compile this. Most don't follow the standard anyways, because they don't treat writing to a memory location as side effect.

A large source of gotchas in C are the standard libraries. For example here's a taste of the trouble its locales cause: https://github.com/mpv-player/mpv/commit/1e70e82baa9193f6f02...

skitter··on Removing garbage collection from the Rust language (2013)
In JRE terms, Rust doesn't have Exceptions, but it has Errors.
skitter··on Using LD_PRELOAD to cheat, inject features and investigate programs
Similarly ldd – which is mentioned in the article – works by setting LD_TRACE_LOADED_OBJECTS, which then gets picked up by Linux's dynamic linker, so any program that doesn't use it can just do whatever instead.
skitter··on GitHubGuessr
When hovering over an item that item is highlighted in pale lavender for only a moment before the highlight moves to the first entry.
skitter··on Maybe Rust isn’t a good tool for massively concurrent, userspace software
It's not intrinsic to async functions; you can block on a future inside another future via e.g. pollster or even manual polling.
skitter··on Maybe Rust isn’t a good tool for massively concurrent, userspace software
Technically, you can break Go's memory model via race conditions: Write to an interface on one thread while reading it from another and you may read the old vtable pointer but new data pointer / the other way around. Same goes for slices with data/length/capacity.
skitter··on Google Chrome pushes browser history-based ad targeting
Firefox does do this.
skitter··on A JVM in Rust part 5 – Executing instructions
When storing an object in an array, the value is checked to be a Value::Object (which can't be null), but you also have Value::Null, so storing null in an array fails (I think). Storing null in local variables, a static field or an instance field works fine.
skitter··on A JVM in Rust part 5 – Executing instructions
VM creation is using unsafe (the line I pointed out above). You're right, I can't find any deallocation either – but weirdly it /does/ segfault (or sometimes have other memory related errors) if I drop the VM while it's heap is still referenced.

The thing with a tighter bound on the lifetime is that VM carrying a lifetime for itself is fundamentally flawed. A solution would be to remove said lifetime, and have all methods on VM that return lifetimed objects take said lifetime from the reference to the VM.

skitter··on A JVM in Rust part 5 – Executing instructions
Your understanding of Rust is correct, but the code uses unsafe: https://github.com/andreabergia/rjvm/blob/93e7e48db085e780b0...

As a result, when the VM gets dropped, the memory gets deallocated even if there are still objects that reference it.

Somewhat related, there also is the issue that when you create multiple VMs, you can use classes/objects/… created by one VM with another.

skitter··on A JVM in Rust part 5 – Executing instructions
You're right there – It looks like the author is trying to express "this lifetime lasts as long as the VM exists", which isn't possible to express in Rust. For VM::new, the callsite just picks a lifetime that lasts long enough – even if that outlasts the VM, making the lifetime useless. This is a bug and unsound.
skitter··on Jacobin: A more than minimal JVM written in Go
You're right, but that's what's meant - using the Go GC vs also implementing a custom one.
skitter··on Jacobin: A more than minimal JVM written in Go
If you want near-go-like performance, Jacobin doesn't help you either.
skitter··on Rust vs. Go in 2023
Technically, there's memory unsafe memory sharing: Interfaces and slices are mutable and consist of multiple word that are accessed without synchronization, sharing a reference to a interface or slice between goroutines means you can get a mismatch between vtable ptr/data ptr or data ptr/length.
skitter··on Why Static Languages Suffer from Complexity (2022)
Rust has those types as Saturating<u32> and Wrapping<u32>.
skitter··on Swap_8_and_9: A simple import can modify the Python interpreter
You don't even need C:

    ctypes.c_int.from_address(id(8)+24).value = 9
skitter··on WASI: WebAssembly System Interface
Rust's (and other languages) memory safety doesn't come from hardware features. Implementing memory safety at the language level means that you don't care about whether the data sits in a paged mapped as read-only, because the language already makes sure you're not writing to said data.

Besides, that's the safety of the code running inside the VM. Wasm is about the safety of the host.

skitter··on WASI: WebAssembly System Interface
Nope, that's just UB, so you cannot know what the code will do. Case in point, running it on linux (compiled via clang) doesn't trigger a segvault for me:

    main:
        .cfi_startproc
    .Lfunc_end0:
        .size       main, .Lfunc_end0-main
        .cfi_endproc
skitter··on Why Rust helps even if you have to use a lot of `unsafe`
Eh, Hare expects you to write and rewrite collections like hashmaps yourself. It just looks like a less flexibe and less useful Zig.
skitter··on Nim 2.0
Was about to bring up that thread. Having a dictator for life isn't a good combination with that dictator going on unprompted, unhinged rants.
skitter··on Unicode is harder than you think
That would be great, but that article is about recommendations for applications running on Windows, not about what valid file names applications may encounter. Here's a counter-example: https://github.com/golang/go/issues/32334
skitter··on Unicode is harder than you think
Because that's how UTF-8 is defined[1]. WTF-8 lifts that restriction.

[1] https://simonsapin.github.io/wtf-8/#utf-8

skitter··on Unicode is harder than you think
Annoyingly, Java, JavaScript, Windows file paths and more don't quite use UTF-16 (well, even if they did, that would be annoying) — they allow unpaired surrogates, which don't represent any Unicode character. So if you want to represent e.g. an arbitrary Windows file path in UTF-8, you can't; you have to use WTF-8 (wobbly transformation format) instead.
skitter··on Before you try to do something, make sure you can do nothing
The "black triangle moment": https://web.archive.org/web/20050306071700/http://www.rampan...
skitter··on I have written a JVM in Rust
I'm not sure what you mean? Mutability wasn't the issue, lifetimes was. It already implemented interior mutability according to Java's rules.
skitter··on Python: Overlooked core functionalities
I'm annoyed at the reason that any/all have to be on this list. If they (and map, filter, …) were methods, you could just write `foo.` and your IDE could show you what methods are available. Postfix would make things easier to read too:

    bar.baz()\
       .filter(some_filter)\
       .map(some_op)\
       .min()\
       .foo()
Data/control flows from top to bottom. One operation per line. But with freestanding functions:

    min(map(some_op, filter(some_filter, bar.baz()))).foo()
To follow the flow of data/control, you start in the middle, go right, then skip left to filter, read rightwards to see which filter, skip left to map, read rightwards to see what map, go left to min, then skip all the way to the right. Just splitting it into multiple lines doesn't help, you need to introduce intermediate variables (and make sure they don't clobber any existing ones) and repeat yourself whether they clarify things or not. The same issue exists for list/dict/set comprehensions.
skitter··on I claim Rich Hickey is wrong about non-null arguments to functions (2020)
This is a breaking change too, as it can break type inference: https://play.rust-lang.org/?edition=2021&gist=8d528bcec2b92b...
skitter··on I have written a JVM in Rust
Funnily enough I did the same in an early wip version of my toy JVM. Ended up using unsafe to use 'static references internally but only hand out wrappers that include a reference to the JVM. This also ensures that objects/classes/… from one JVM can't be used in another one.
skitter··on Accidentally Load Bearing
Is this an instance of Cole's law: The fastest way to get the right answer is to post the wrong answer?
← PreviousPage 4 of 8Next →