6 ms·
Improving C# Memory Safety
- pjmlp 5mo agoMost likely a side effect related to Windows team finally giving some C# love, instead of COM and C++, given the comparisons between C# 16 with Rust and Swift in a few article sections.
- moomin 5mo agoThe Windows team is talking to DevDiv again? Satan's putting on his ice skates right now.
- pjmlp 5mo agoOne can only hope. C++/WinRT is in maintenance, and you will notice the WinUI 3.0 does most of their demos, and gallery with C#.
- moomin 5mo agoIt would be nice if any display API actually covered the entire API with the exception of the actual OS API…
- EFLKumo 5mo agoIn terms of XAML UI, C++/WinRT struggles. When it was released, C++ just lacked good reflection methods, and many practices that were easily achieved in C#, such as MVVM, data bindings, were difficult to migrate. I think this prevented C++ from re-entering modern Windows development practices.
- pjmlp 5mo agoOn the contrary, C++/CX was (still is) a great development experience, for the very first time, Microsoft hat something that could rival C++ Builder. Instead an small group rioted, came up with C++/WinRT with support from management and complete disrespect for paying customers. Now a decade later, C++/WinRT in in maintenance, the roadmap vision shown at CppCon 2017 unfulfilled, and the same team is now having fun with Rust in windows-rs. > This isn't meant as a negative statement. cppwinrt has reached all of its goals and is generally considered complete and largely bug-free (1). Whether WinRT/WinUI/WinAppSDK is the future is debatable. My experience has shown me that the Windows operating system is at its best when you embrace the Windows API as a whole, including Win32/COM/WinRT, and not just the latest shiny wave. You can see this in action with the popularity of projects like win32metadata and windows-rs that support both WinRT and non-WinRT APIs seamlessly. Quote from the devs on Github. Thanks for nothing, I guess.
- EFLKumo 5mo agoMaking a XAML UI is fundamentally authoring a WinRT interface, I guess. And for cppwinrt, Microsoft's solution is like describing in so-called MIDL .idl files, compiler generating cpp stubs, copying these stubs and filling in implementations. After static reflection introduced in cpp idk if this process could become better, but Microsoft just left cppwinrt in maintenance mode, it's impossible I guess. On the Rust side, IMO the windows-rs even has not thought about authoring new com interfaces, only consuming or impl-ing existing ones. In fact the experience of consuming windows apis in rust feels good if one would like to get rid of C++. Rust with NAPI or BoltFFI etc. offers an maintaining-friendly option for cross-platform app authors to interact with the OS more deeply. So in conclusion the situation right now is that windows apis just become not so unapproachable, while in-depth things keeping comfortable only with C# or .NET.
- superjan 5mo agoWhat you can do in C# today is convert any unsafe pointer to Span whenever you get your hands on it, and pass around slices. You can still drop down to ‘fixed’ when it turns out you need it for performance.
- legulere 5mo agoWith fixed you do pinning on GC memory, which can have a negative performance effect. You can also do unchecked pointer arithmetics on references with the Unsafe class, which avoids that. A lot of the methods of Span use that internally.
- sedatk 5mo agoI could say that the perf difference between spans and unsafe pointers in most cases is just zero, if not in favor of spans at times due to the optimized helper methods or just better code generation. Add the safety benefits to the mix, and it's a no brainer. So, unsafe pointers may not have an edge for performance anymore. They might have other uses cases of course: interop, etc.
- SideburnsOfDoom 5mo ago> The unsafe keyword is being redesigned OK, I see a lot of C# code often and over a long time. I see the "unsafe" keyword used approximately never. I'm sure that this is useful for some cases. But not everyday things for most of us. If we did use it, it would be carefully isolated in a library for a specific purpose.
- pjmlp 5mo agoMany of us use it in scenarios where others would write a blog post about a rewrite in Rust, C++ or whatever. CLR was designed to support languages like C++, yet many don't learn the knobs.
- Weebs 5mo agoAny lesser known knobs one should know? I'm considering a .NET backend for my compiler
- pjmlp 5mo agoIf on Windows, one is to see what C++/CLI would generate, with ildisam or similar tool. You can also emit MSIL for what you actually want to do, with low-level bytecodes. Then there is unsafe, ref structs, stack allocation, fixed buffers, scoped types, manual memory management, array pools, memory pipelines, the various span variants.
- tialaramex 5mo agoThis moves C# to a more modern systematic understanding of what this keyword is for, but it'll remain very rare in C# the same way it's rare in Rust, and presumably in Swift. The choice of keyword "unsafe" is partly psychological. Turns out if you called this exact same feature "trusted" or whatever the programmers don't have the appropriate feelings about it. They want to write trusted code, they don't want to write unsafe code, so making them write the keyword "unsafe" provides that psychological disincentive.
- 5mo ago
- caspper69 5mo agoThey are aligning more closely with the Rust 2024 model for unsafety, which requires inner annotations at the point of unsafety in addition to notation of the function (unless it is the safe-unsafe boundary) plus it imposes a requirement for a SAFETY doc notation for describing the specific invariants the caller must enforce to uphold the safety guarantees. Not terribly onerous in my opinion. I maintain a few native library wrappers on nuget, so I will have to do some updates around IntPtr usage, but this doesn’t seem like it will be terribly painful in my case. Thankfully I don’t do much marshalling. Plus you get a nifty badge on nuget for making your library safe. The blurb toward the end about Rent/return makes me a bit nervous though. They say they’re not going full borrow checker, but rent at least sounds an awful lot like borrow to me. Details were basically non-existent though. I guess I wonder what the end game is here though. The more they make C# like Rust with a GC, the less incentive people have to use C# except maybe to support legacy work. I am still far more comfortable in C# than Rust, and I believe C# is superior for e.g. web, but over time this advantage could be lessened quite a bit as the Rust ecosystem continues to grow.
- masklinn 5mo ago> The blurb toward the end about Rent/return makes me a bit nervous though. They say they’re not going full borrow checker, but rent at least sounds an awful lot like borrow to me. Details were basically non-existent though. Since they state outright that they're not going for a borrow checker, I would assume they're going for "second class references": the borrow checker is both powerful and complicated because references are first-class types: you can pass a reference as parameter, you can return a reference, and you can store a reference. You can get a lot of the benefits (though also lose a fair amount of expressive power) if you drop the last two and only allow borrows downwards, and that is way easier to track. Graydon Hoare's original conception of rust used second-class references (https://graydon2.dreamwidth.org/307291.html#:~:text=First-class%20%26 https://graydon2.dreamwidth.org/307291.html#:~:text=First-cl...). The Val language uses second-class references. Hylo (formerly Val) uses second-class references under the name of mutable value semantics (https://www.jot.fm/issues/issue_2022_02/article2.pdf https://www.jot.fm/issues/issue_2022_02/article2.pdf). Although the rent/return case doesn't even seem like a references concern, instead it's affine types which is orthogonal: after you `Return` an array to the pool, you want the array to become inaccessible to the caller (you could make the value linear, but as the text explains missing a `Return` is a safe leak it doesn't look like that's in scope). Rust mutable references are affine but you don't need references to do this...
- gertlabs 5mo agoC# is one of the best languages we evaluated for LLM problem solving. In fact, many strongly typed, lower level languages perform well in our testing (this isn't to say that the solutions are more maintainable, but the LLMs come up with better ideas when writing C# or Rust than Python). Google models especially, for whatever reason, outperform in C#, not Golang. Data at https://gertlabs.com/rankings?provider=google https://gertlabs.com/rankings?provider=google
- reactordev 5mo agoThis is why C# is superior to C++ for game development (not the graphics low level, but the game play higher level). Being able to use Events, ECS, Reflection, Dynamic code is a god send. I have written game engines in C# and I still find myself defaulting to it anytime I think about Vulkan. I even published my own bindings for it. The best thing about .Net unfortunately is also one of its worst. The deployment and packaging situation. It’s better than it’s been but it’s still a freaking mess. A mix of undocumented cli commands and wacky xml so that I can get an amalgamated build… or if I wanted to target another OS… or something of that nature. Even adding a project reference to a project, you have to go the long way round and use the cli commands. It’s better than having to install Visual Studio Ultimate but I wish they would put some love into their VSCode extension to give .Net some more powah. Other than that, if you need Cish speed but need to support a GUI or something, C# is a good choice. If you’re happy with HTML UI, use that and forget C#. The UI cross platform situation is basically MIA.
- scott01 5mo agoI respectfully disagree — a lot of conveniences that C# provides produce GC trash which will cause frame spikes. I remember having had to add a non-allocation string.contains alternative at one project. Lambdas and linq also have this problem, or if a string is passed through native-c# boundary. Language itself is really nice though :)
- reactordev 5mo agoI think you need to revisit your biases
- Dwedit 5mo agoAre they finally marking all those functions that use IntPtrs as unsafe? (such as Marshal.Copy)
- orphea 5mo agoNot really, because IntPtr is just a native-sized integer. Marshal.Copy will certainly be marked unsafe, as will anything else that touches unmanaged memory.
- WorldMaker 5mo agoThis change suggests that passing pointers is "generally safe", the unsafe boundaries are when they are de-referenced. It sounds like the Marshal methods are probably going to get a lot of surprising new safety warnings, but not all of them just because of the use of IntPtr. This change does open more opportunities to switch IntPtr to more explicit type-safe options like void* or byte* as the new compiler no longer needs unsafe {} blocks around just passing around pointers from one function to another.
- effnorwood 5mo agojust use perl instead
- ryanshrott 5mo ago[flagged]
- northlondoner 4mo agoSuperb development. This would elevate C# into first class systems language, Linux Kernel level.