Perversion with unsafe C#, memory stack allocation - c#

Here I'm trying to work with unsafe features of C#: http://ideone.com/L9uwZ5
I know, that such way in C# is worst, and I want to admit, that there is some info in the topic. Look at the word "perversion".
I would like to implement quick sort in C# like pure-C way (not even C++). It could be crazy, but just want to look deep at the possibilities of unsafe C#.
I was always trying to use stackalloc operator. I know, that it's an allocation from stack, not from heap, and that's why I get failure with executing of my program.
But I was confused when I haven't seen any exception/error in this program.
Why didn't I get any explicit exceptions/errors?
Also, as you see the commented part of code:
struct Header
{
internal int* data;
};
Header* object_header = stackalloc Header[sizeof(Header)];
object_header->data = stackalloc int[length];
I can't compile it with the last line. C# compiler tells, that in this expression stackalloc couldn't be used. Why? data is int* type, so why did error occur here?
I want just to use stack frame and not to use heap.
I know, that there is another way, but it's an allocation from heap.
int*[] data = new int*[length * sizeof(int)];
IntPtr result = Marshal.AllocHGlobal(Marshal.SizeOf(length * sizeof(int)));
Marshal.WriteInt32(result, 0);
for(int i = 0; i < length * sizeof(int); i++) d[i] = (int*)result;
For example, but it's not stack allocation.
How could I solve my perversion task, explicitly with the stack-allocation and pure-C style syntax in C# language.
That C# wasn't created for such aims and such features are silly - I know, but the main question is not about significance, it's about such features.

Marc showed the workaround, I'll try to explain why this is required. You are writing, in effect, unmanaged code but the method is still very much a managed method. It gets compiled from IL into machine code and its stack frame and cpu registers will be searched by the garbage collector for object references.
The jitter performs two important duties when it compiles a method. One is obvious and highly visible, translating the IL to machine code. But there's another very important task and it is completely invisible, it generates metadata for a method. A table that shows what parts of the stack frame contains object references and what parts store pointers and value type values. And at which points in the code a cpu register will store an object reference. Also, at what point in the method code an object reference goes out of scope. The reason for GC.KeepAlive(), a pretty unique method that generates no code at all.
The garbage collector needs that table to reliably find object references. This table however has only one level of indirection. It can describe the stack space allocated for object_header and mark the pointer and the pointed-to stack area as "do not scan for object references". It cannot describe the chunk of stack space when you directly assign object_header->data. It doesn't have the extra indirection to sub-divide the stack into smaller sections and describe Header. Using the dummy local variable solves the problem.

stackalloc wants to assign to a variable. The following works but you would have to be really careful to unassign that before leaving the method - if you leave object_header->data point to a location in the stack: bad things:
int* ptr = stackalloc int[length];
object_header->data = ptr;
The fact that it must be assigned to a local variable is explicit in the specification:
local-variable-initializer:
…
stackalloc-initializer
stackalloc-initializer:
stackalloc unmanaged-type [ expression ]

Related

How C# returns Structs

Structs are value types and thus are fully copied every time there is a manipulation on the struct. Since they are value types, structs are allocated in the stack and not in the heap.
I can see how structs can degrade the performance of methods when structs are passed as parameters, since they will be always copied in the stack, specially if they are big with lots of inner fields.
But I am curious about how C# deals with the return of structs.
In C the return is made by registers, or by reference using the heap if the value to be returned is too big for the registers. And practically all C# struct tutorials say structs lives in the stack, never in the heap.
So in the following code:
MyStruct ms = GetMyValue();
Where GetMyValue() is
MyStruct GetMyValue();
How will C# deal with the return of the struct for the ms variable? Specially if it's is too big for the registers? Will it in fact copy it to the heap and then copy it back again to the caller of the method and assign it to ms?
EDIT:
To address the comments left in the post:
I have read a few tutorial on C# structs before posting this, this tutorial in particular uses the word stack more times than I bother to count. And this MSDN tutorial also speaks about the stack, although it's from 2003, I don't think structs changed since then.
I am aware this might not be realted at all with C# but in fact be a matter of the JIT compiler it self or the CLR or something else I am not aware of. That's the purpose of my question, to learn more about the inner workings of C#, even if this is not actually related to the language itself.
There are C function call conventions, the best support for my Post is this StackOverflow post. When I first posted it in here I just said what I remembered, but since the SO answer says:
As for your specific question, it depends the ABI. Sometimes if the return value is larger than 4 bytes but not larger than 8 bytes, it can be split into EAX and EDX. But most of the time the calling function will just allocate some memory (usually on the stack) and pass a pointer to this area to the called function.
I might be wrong on this one, and I say might, because the answer says usually.
The true reason why I want to understand how structs are handled is because I have a project where I have to read a Serial Port multiple times to poll for data, this data will be returned by a method.
Since the data is just some bytes I thought I could get some performance out of structs instead of using a class to abstract the bytes incoming by the Serial Port, but if the return would pass the struct as a heap allocation my expectations on performance increase could be false.
Yes, I can make a simple test and compare performance, I know, but I wanted to actually learn how it's done behind the curtains, and not only memorize the outcome of my simulation. I like to know how the things that I work with actually work, and not only learn how to use them.
Value types are not only located on a stack. They also live in fields and in arrays. The key distinction to reference types is that value types are copied by value and have no identity. The stack vs. heap idea is false.
In C the return is made by registers, or by reference using the heap if the value to be returned is too big for the registers
The heap is not involved. The caller allocates spaces for the return value to be placed in. It passes a pointer to that space. The callee can fill that space. The .NET CLR does this as well. Of course this is an implementation detail.
but I wanted to actually learn
This is very good. You could not have tested what I just told you. You need to be a little more critical in what you believe what others say. Either you had bad tutorials or you read them in an imprecise way.
I can see how structs can degrade the performance of methods when structs are passed as parameters, since they will be always copied in the stack
This is not always the case I think. I'm not quite sure but I think the JIT can sometimes pass structs in registers. The .NET JITs really do not optimize much but I think this is an optimization that works to a certain degree. Probably driven by the existence of some one-field structs such as DateTime.
structs do not always live on the stack. if you allocate a struct inside of a function, it lives its life on the stack. if it's a field of a reference type(class/array(implicitly derived from System.Array/Object), it lives its life on the heap. as far as how theyre returned, that might be up to the ABI for that CPU architecture.
from the sounds of it, you've never dealt with IL/assembly/code generation, so lets build a dynamic method thats equivalent to MyStruct ms = GetMyValue()/what the compiler would generate in context of the word stack. "things" are never actually returned. thing(s, in a tuple sense i'm sure), are pushed onto the stack, and then a return instruction is emitted. leaving the return value(s) for the caller. we're going to assume GetMyValue() allocates a new MyStruct and assigns it to a local variable. the generated code would look something like this(i extend the ILGenerator class):
ILGenerator generator = dynamicMethod.GetILGenerator();
generator
.DeclareLocal(typeof(MyStruct))
.EmitCall(OpCodes.Call, typeof(EncapsulatingClass).GetMethod("GetMyValue"))
.Emit(OpCodes.Stloc, 0);
what happens here is(some of this is my assumption on how the CLI runtime works):
the calling function reserves a slot of typeof(MyStruct) at the current local list index.
GetMyValue() is called, reserves a MyStruct local the same way the method we are building does, emits an OpCodes.Newobj, which allocates and adjusts ESP(extended stack pointer) downward in the amount of sizeof(MyStruct), emits OpCodes.Stloc to store ESP minus sizeof(MyStruct) into the reserved local index, does some stuff with its fields, calls Emit(OpCodes.Ldloc, 0) to push the address the local points to onto the evaluation stack for the calling function, and emits an OpCodes.Ret to return.
the calling function emits an OpCodes.Stloc to store(copy) the contents of the MyStruct the top of the evaluation stack points to(how this happens, well i'm sure the answer is it depends, unfortunately), at local index 0.
i'm not an expert on how the CLI runtime is constructed by any means, so a lot of this is an assumption of what happens. take it with a grain of salt, and i'm by no means a CPU engineering expert. how the instruction stream segment of OpCodes.Ldloc, OpCodes.Ret, OpCodes.Stloc -- ms = GetMyValue() -- is treated, is probably up to how the JITer translates the IL into actual cpu specific machine instructions. such as X86. what determines if a struct will be returned into a register, is probably limited to one register only, so whatever the biggest register is, and if whatever struct will fit inside of it. i know CPU's can combine registers for memory offsets, but i'm not sure if that applies to returning structs inside of multiple registers. another thing to keep in mind, GetMyValue() went out of scope, which means the struct GetMyValue() allocated, in a scope sense, doesn't exist anymore, but in a stack sense(where it was allocated), it does, so the JITer could very well have just taken the address OpCodes.Ldloc pushed onto the stack, and placed it directly into the callers local index 0. since nothing can possibly copy it anymore due to the function returning. making the caller the new owner of the struct. avoiding any copying and registers altogether in this special case. this might be where calling conventions come into play as well. the problem is, if you allocated three structs in GetMyValue() for whatever reason, returning any struct after the first struct allocated would break that optimization, which is where the next optimization, return the struct inside a register(if it fits), comes into play. leaving the worst case scenario, copying its contents purely onto the stack again for the caller. i could be wrong, and anyone is more than welcome to chime in and correct me. a good place to start, would be github and see how the runtime handles OpCodes.Ldloc/Stloc for structs. i would imagine that's a good spot to look when it comes to getting the answers you need.
EDIT: any tutorial you've read that says structs are always allocated on the stack, have them all DDoS'd.

Why does stackalloc have to be used as a variable initializer?

I'm writing some unsafe code in C# (follow-up to this question) and I'm wondering, why exactly does the stackalloc keyword have to be used as a variable initializer? e.g. This will produce a syntax error:
public unsafe class UnsafeStream
{
byte* buffer;
public UnsafeStream(int capacity)
{
this.buffer = stackalloc byte[capacity]; // "Invalid expression term 'stackalloc' / ; expected / } expected"
}
}
But re-assigning the results from a local temporary will not:
public UnsafeStream(int capacity)
{
byte* buffer = stackalloc byte[capacity];
this.buffer = buffer;
}
Why isn't the first version allowed, and what evil things will happen if I attempt the second version?
Your stack is looking something very roughly like this:
[stuff from earlier calls][stuff about where this came from][this][capacity]
^You are here
Then you do stackalloc and this adds two things to the stack, the pointer and the array pointed to:
[stuff from earlier calls][stuff about where this came from][this][capacity][buffer][array pointed to by buffer]
^You are here
And then when you return the stuff most recently put on the stack, the locals of the current function, its return address, and the stackalloced buffer are all simply ignored (which is one of the advantages of stackalloc, ignoring stuff is fast and easy):
[stuff from earlier calls][stuff about where this came from][this][capacity][buffer][array pointed to by buffer]
^You are here
It can be overwritten by the next method call:
[stuff from earlier calls][stuff about where this came from][this][new local1][new local2]o by buffer]
^You are here
What you are proposing, is that a private field, which is to say a part of an object on the heap (a different piece of memory, managed differently) hold a pointer to the buffer that has been half-overwritten by completely different data, of different types.
Immediately consequences would be:
Attempts to use buffer are now fraught because half of it is overwritten by item, most of which aren't even bytes.
Attempts to use any local is now fraught, because future changes to buffer can overwrite them with random bytes in random places.
And that's just considering the single thread involved here, never mind other threads with separate stacks perhaps being able to access that field.
It's also just not very useful. You can coerce a field to hold an address to somewhere on a stack with enough effort, but there isn't that much good one can do with it.

Can't stackalloc be used in C# to initialize a previously declared pointer?

I just discovered the stackalloc notation of C# has an unbelievable quirk, please see the following code:
// int *p;
// p = stackalloc int[42]; // won't work!
// Error CS1525: Unexpected symbol `stackalloc' (CS1525)
int *p = stackalloc int[42]; //works
My intention is to use stackalloc in a ternary expression like this:
int *p = size > 0xFFFFF ? (int*)Marshal.AllocHGlobal(size).ToPointer() : stackalloc int[size];
The totally unexpected strike of compiler shocked me hard. I'd really appreciate if someone could shed some light on this strange behavior. I've tested it on both mono and .net, neither works.
http://msdn.microsoft.com/en-us/library/cx9s2sy4(v=vs.100).aspx
You can use stackalloc only when declaring and initializing a local variable.
People have already answered this, that you can only use it when declaring and initialising a local variable: http://msdn.microsoft.com/en-us/library/cx9s2sy4(v=vs.110).aspx.
However, if you're wondering what the reason for this is, it's lexical scoping. A local variable declaration creates a lexical scope containing one or more basic blocks. The CLR requires that the stack pointer is at the same position at the beginning and end of each such basic block. Control transfer statements can only jump to the first instruction of a basic block.
When you use stackalloc, then the compiler needs to make some room on the stack by decrementing the stack pointer and incrementing it again when the allocated variable goes out of scope.
If you're inside an expression evaluation, there will be temporary values on the stack, so where should the compiler put that variable? Allocating it at the beginning of the method is not an option because you can use an expression to specifiy the size.
Therefor, you have to explicitly tell the compiler where you want that variable to be allocated and for how long the memory should be kept.
Understandable it is a quirky behavior...and I do not have the answers as to why, but it is documented on MSDN
see here:
http://msdn.microsoft.com/en-us/library/cx9s2sy4.aspx

Unsafe method to get pointer to byte array

is this behaviour will be valid in C#
public class MyClass
{
private byte[] data;
public MyClass()
{
this.data = new byte[1024];
}
public unsafe byte* getData()
{
byte* result = null;
fixed (byte* dataPtr = data)
{
result = dataPtr;
}
return result;
}
}
If you are going to turn off the safety system then you are responsible for ensuring the memory safety of the program. As soon as you do, you are required to do everything safely without the safety system helping you. That's what "unsafe" means.
As the C# specification clearly says:
the address of a moveable variable can only be obtained using a fixed statement, and that address remains valid only for the duration of that fixed statement.
You are obtaining the address of a moveable variable and then using it after the duration of the fixed statement, so the address is no longer valid. You are therefore specifically required to not do precisely what you are doing.
You should not write any unsafe code until you have a thorough and deep understanding of what the rules you must follow are. Start by reading all of chapter 18 of the specification.
This code will compile just fine however it will lead to runtime issues. The code is essentially smuggling out a pointer to an unfixed object in the heap. The next GC which moves the MyClass type around will also move the data reference with it and any previously returned values from getData will now point to the incorrect location.
var obj = new MyClass();
unsafe byte* pValue = obj.getData();
// Assuming no GC has happened (bad assumption) then this works fine
*pValue = 42;
// Assume a GC has now happened and `obj` moved around in the heap. The
// following code is now over writing memory it simply doesn't own
*pValue = 42;
Did that last line cause the app to crash, overwrite a string value in another type or simply poke a value into an uninitialized array and just screw up a math problem else where? You have no idea. Best outcome is that the code just crashes quickly but in all likely hood it will do something far more subtle and evil.
You could use the Marshal.StructureToPtr() method instead of unsafe magic :)
StructureToPtr copies the contents of structure to the pre-allocated
block of memory that the ptr parameter points to.
Marshal.StructureToPtr Method (Object, IntPtr, Boolean)
This code will not work (it will compile but at runtime it will cause problems). Once the fixed region ends, the data is no longer pinned.
No, once you leave the fixed block, the value of result is no longer valid (it may coincidentally be valid if the GC hasn't run).
The proper way to do this kind of operation is to either have a reference to a byte[] in unmanaged memory that you access through C# code, or copying the managed array into unmanaged memory.

Displaying the value of a reference to an object

In C++ it is fairly simple to display the actual value of a pointer to an object. For example:
void* p = new CSomething();
cout << p;
Is there a way to do something like this in .NET?
The value of doing this would/could only be educational, e.g. for purposes of demonstration as in displaying a value for students to see rather than just comparing for reference equality or null (nothing) to prove shallow copies, immutability etc.
You can use GCHandle to get the address of a pinned object. The GC can move objects around so the only sensible address to get is one of a pinned object.
GCHandle handle = GCHandle.Alloc(obj, GCHandleType.Pinned);
Console.WriteLine(handle.AddrOfPinnedObject().ToInt32());
handle.Free();
Remember though that GCHandle will only pin objects that are primitive or blittable types. Some objects are blittable (and you can set it up for demo purposes so it works) but any reference type will not be blittable.
You'll need to add an explicit blittable description using [StructLayout(LayoutKind.Sequential)] or use the debugger to directly inspect addresses of object that do not meet these criteria.
If this is for education purposes, I suggest you use a debugger instead. If you load SOS.dll (which is part of the .NET framework) into WinDbg or even Visual Studio, you can examine the actual objects in memory.
E.g. to list the heap use the !dumpheap -stat command. The !do command dumps a mananaged object on the specified memory address and so forth. SOS has numerous commands that will let you examine internal .NET structures, so it is a really useful tool for learning more about the runtime.
By using the debugger for this, you're not restricted to looking at demo applications. You can peek into the details of real applications. Also, you'll pick up some really useful debugging skills.
There are several excellent introductions to debugging using WinDbg + SOS. Check Tess' blog for lots of tutorials.
RuntimeHelpers.GetHashCode will give you an identity-based hash code. In practice, this is probably based on address. As explained:
"RuntimeHelpers.GetHashCode is useful
in scenarios where you care about
object identity. Two strings with
identical contents will return
different values for
RuntimeHelpers.GetHashCode, because
they are different string objects,
although their contents are the same."
Interning of string literals is the main possible exception. This is actually the same in C++.
I understand that if you provide the compiler the /unsafe option, you will be allowed to write 'unsafe' code, and with it have access to pointers.
I haven't tested this but found it in this artice
Edit:
Seems the main thing to remember is that you would have to mark any code using unsafe code with the unsafe keyword:
unsafe public static void Main()
In .Net you don't work with pointers at all. So you would create reference objects, of which you can always see the value.
When comparing reference objects, the references are compared, not the actual values! (Except for comparing strings, where the '==' is overloaded).
Maybe an .Net example of what you want to demonstrate would elaborate things...
You can retrieve the address of an object in .NET, such as with unsafe code, but the address you get back will only be temporary -- it'll be a snapshot as of the point where you take the address.
The next time a garbage collection happens, the address of your object is likely to change:
If the object is no longer referenced from anywhere, it will be collected, and some other object will occupy that address
If the object is still being referenced, it will probably be promoted to a higher generation (and therefore moved to a different GC heap). Alternatively, if it's already in generation 2, it will probably be moved in memory as the heap is compacted.
The existence of the garbage collector is the reason why the int* pointer in #Jesper's exists in the scope of a { } block. The pointer is fixed only within that block; once execution leaves the block, the object is entitled to be collected and/or moved.
unsafe
{
object o = new Object();
int *ptr = &o; //Get address
Console.WriteLine((int)ptr); //Write address
}
You need to compile this with the /unsafe switch

Categories

Resources