Hacker News new | ask | show | jobs
by pkolaczk 1830 days ago
And what did you try to prove here? There is no use after free and no runtime error in this rust code. The socket stays valid since the moment of its creation and for the whole lifetime of the network component. It gets moved out of nested scope properly and gets closed after leaving the outer scope, after dropping the NetworkComponent struct.

The "oops" comment is invalid in your Rust example because the socket is still valid at that point.

Which is totally different than what would happen in C#, where you'd get use-after-free bug (actually use-after-close).

Try with resources is not RAII. It is a lot weaker.

1 comments

> foo.do_sth_with_socket(); // oops, runtime failure, socket closed

Happens just as well in Rust, why do you think I gave you a Playground link.

If you want, I can shut up the cleverness with a cargo build example instead of a dummy playground example.

The playground link confirms the socket is closed after dropping networkComponent.

Last two lines of the output:

    Dropping NetworkComponent
    Dropping NetworkSocket
Btw: you probably fooled yourself by accidentally creating 2 sockets, and indeed the first one gets dropped immediately when you lose (overwrite) the reference to it. Use Option to avoid that.
You forgot another line, it was actually:

    Creating NetworkComponent
    Dropping NetworkSocket
    Dropping NetworkComponent
    Dropping NetworkSocket
Besides, you forgot another tiny detail,

By replacing the socket now the port number is another one, and all processes that had open connections to that port will now crash, or have messages dropped without getting why.

I can also fabricate plenty of error situations with Rust if you feel so inclined.

And if you were actually serious, you would be aware that there are Roslyn analysers that validate IDispose follows proper RAII patterns, like https://github.com/DotNetAnalyzers/IDisposableAnalyzers

Remember, Rust isn't perfect, and only fixes 70% of existing error patterns, I can have plenty of inspiration with the remaining 30%.

> You forgot another line, it was actually:

No I didn't. That line is totally irrelevant and does not apply to the socket that was passed to the NetworkComponent. It applies to the initial socket you've added which was not even present in the original example. You should have used Option to make your code equivalent.

Anyway, your example failed to show use-after-close in Rust.

> Remember, Rust isn't perfect, and only fixes 70% of existing error patterns

Sure, no-one here debated that. But it fixes/protects from more error patterns than C#, and use-after-close is one of them.

You stated that try-with-resources + struct types are functionally equivalent to RAII. My code proved they were not, because you can trivially make use-after-free, and it is even really easy to do that by accident. There is nothing in the language that protects from leaking a closeable reference from the `using` scope and then using that reference after the scope gets closed. And that leak can happen 10 layers below, when it is not as easily seen as in this trivial example I posted. In Rust you can do it only with explicit `unsafe`; otherwise the typesystem tracks that for you.

> In Rust you can do it only with explicit `unsafe`; otherwise the typesystem tracks that for you.

Exactly, so I can continue this charade by creating such example.

Rust is not a magic bullet, and just like with your "proof" I can provide similar "proof" with unsafe.

Or I can provide an example in D, with has a GC and C++ like RAII, or Swift that also has a GC (ARC is a GC algorithm) and C++ like RAII as well.

I have been playing this game about explainging how to do deterministic resource management in GC enabled languages since I learned Oberon in 1995.

It is always the same pattern.

- "GC languages cannot do X"

- "Actually you can partially achieve X with Y"

- "Yeah, but ....."

So whatever.