Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proposal: Add keywords to support platform-agnostic memory management in unsafe context #4414

Closed
TwoRedCells opened this issue Aug 7, 2015 · 3 comments

Comments

@TwoRedCells
Copy link

(FEATURE SUGGESTION)

Background

C# is a general-purpose language that has traditionally had a strong connection to the .NET framework. As the language gains popularity, it is being used in other ways, such as a scripting language, a source language for cross-compilers, and with microcontrollers with the Micro .NET framework.

I would argue that, as a general purpose language, it should not necessarily require the use of a garbage collector OR a framework/standard library. Specifically, due to a lack of a few keywords, it is currently not possible to allocate and deallocate memory from the heap at the language level. Instead, one needs to use the Marshal classes/methods in the interop part of the framework to accomplish this.

Objective

I would love to be able to write a compiler to directly target machine code (not IL) for microcontrollers, but to do so I would need to write a garbage collector OR a class library to manage the heap. While the latter is possible, albeit a bit clumsy, a GC is just a waste of resources, if not impossible for a chip with memory measured in bytes or kilobytes.

I have also done a lot of high-performance graphics processing development in C#. This is all done in an unsafe context to allow quick access to memory at the byte level. Allocation using Marshal works fine, but it would still be less awkward if it was mapped to a language feature. It is analagous to using malloc in C, which requires a library to access this functionality; however, as a high-level language with some lower-level features, this would provide a consistent and complete toolset to the C# programmer.

Suggestion

Addition of an unmanaged context to demarcate explicit heap allocation.

New keywords:

  • unmanaged
  • delete
  • keep

These carry the following features:
unmanaged defines a context, the same ways that unsafe does. It modifies the behaviour inside that domain. Inside this context:

  • All code is ignored by the GC.
  • Only value types (including struct, enum, pointers) can be declared.
  • Value types can be declared locally on the stack, and will be popped off automatically when out of scope.
  • Normal array declarations are create on the stack. e.g. int[] happy = new int[10];
  • Array declarations assigned to a pointer are allocated on the heap. e.g. float* lucky = new float[20];
  • Unless the stackalloc keyword is used. e.g. double* super = stackalloc double[30];
  • If this seems confusing, I suppose a heapalloc keyword could be introduced.
  • The programmer is responsible for deallocating heap allocations using the delete operator.
  • A compiler error would be thrown when a dynamically allocated pointer goes out of scope without being deleted; unless the keep keyword is used.
internal unsafe class Disco
{
    char* lucky; 

    private void foo()
    {
        int a = 1;

        unmanaged
        {
            int b = 2;
            byte* super = new byte[255];
            lucky = new byte[255];
            byte* happy = stackalloc byte[255];
            byte* ball = new byte[255];
            object o = new object(); // compiler error: reference type declared in unmanaged code.
            int c = b;

            // Do something useful.

            delete ball;
            keep lucky;
        }  // compiler error: super went out of scope without delete/keep.

        int d = b; // compiler error: b is out of scope
    }   

    private unmanaged void bar()
    {
        delete lucky;
    }
}

Summary

The addition of the unmanaged, delete, and keep keywords gives the programmer the tool to manage memory granularly at a low-level in a platform-agnostic way, suitable for low-overhead (microcontroller etc.) and high-performance workflows. By doing so it helps to establish C# as a general purpose language could be compiled directly to machine code with the control of C and the elegance of C#.

While not protecting against buffer overruns or memory leaks (though bounds checking could be discussed), the delete/keep operator pair enforce sober second thought and good habits.

Like unsafe and stackalloc, these are keywords that many programmers will never use in their lifetime; but add value to the language as a whole.

Feedback, suggestions, further idea development welcome.

@TwoRedCells TwoRedCells changed the title Add keywords to support platform-agnostic memory management in unsafe context Proposal: Add keywords to support platform-agnostic memory management in unsafe context Aug 8, 2015
@danieljohnson2
Copy link

I don't think is going to be a viable feature; in particular, if you want to replace C you need to be able to run with no GC, no libraries, and no JITter. You're going to have to cripple C# quite a lot more before you can do that.

C# implicitly allocates at the drop of a hat. Consider boxing: object o = 1 and anonymous functions: EventHandler e = delegate { }. You really need a GC of some kind for this to be tolerable.

You also need at least some of the standard library: stuff like IDisposable and Task<T>, which are used by language features.

You even need a JITter, strictly speaking, because C#'s generic type system allows you to create an indefinite number of new types at runtime. Implementations like .NET Native and Mono's AOT compiler will just crash at runtime if this happens, which is very nasty; if it weren't for iOS I'd consider these things outright useless.

You actually could disallow all this stuff, but I do not think the elegance of C# would survive.

Yet you really would need go this far; if you don't, all you really have is syntactic sugar for malloc, which isn't a good thing- C style allocators are actually pretty slow. You get speed by avoiding heap allocations, not by using a C-style manual heap.

@whoisj
Copy link

whoisj commented Aug 21, 2015

Honestly, I actually like this quite a bit.

@gafter
Copy link
Member

gafter commented Mar 20, 2017

We are now taking language feature discussion on https://github.com/dotnet/csharplang for C# specific issues, https://github.com/dotnet/vblang for VB-specific features, and https://github.com/dotnet/csharplang for features that affect both languages.

See also #18002 for a general discussion of closing and/or moving language issues out of this repo.

@gafter gafter closed this as completed Mar 20, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants