2012-11-26 10 views
5

Hier Ich versuche, mit unsicheren Funktionen von C# zu arbeiten: http://ideone.com/L9uwZ5Perversion mit unsicheren C#, Speicherstapel Zuordnung

Ich weiß, dass eine solche Art und Weise in C# ist am schlechtesten, und ich will zugeben, dass es einige ist Info im Thema. Schau dir das Wort "Perversion" an.

Ich möchte schnelle Sortierung in C# wie Pure-C-Art (nicht einmal C++) implementieren. Es könnte verrückt sein, aber nur tief in die Möglichkeiten von unsicherem C# schauen.

Ich habe immer versucht, stackalloc Betreiber zu verwenden. Ich weiß, dass es eine Zuweisung vom Stapel ist, nicht vom Heap, und deshalb bekomme ich Fehler bei der Ausführung meines Programms.

Aber ich war verwirrt, wenn ich keine Ausnahme/Fehler in diesem Programm gesehen habe.

  • Warum habe ich keine expliziten Ausnahmen/Fehler erhalten?

Auch, wie Sie den kommentierten Teil des Codes zu sehen:

struct Header 
{ 
    internal int* data; 
}; 

Header* object_header = stackalloc Header[sizeof(Header)]; 
object_header->data = stackalloc int[length]; 

Ich kann es nicht mit der letzten Zeile kompilieren. Der C# -Compiler sagt, dass in diesem Ausdruck stackalloc nicht verwendet werden konnte. Warum? Daten sind int * Typ, warum ist also hier ein Fehler aufgetreten?

Ich möchte nur Stapelrahmen und nicht zu Heap verwenden. Ich weiß, dass es einen anderen Weg gibt, aber es ist eine Zuweisung von 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; 

Zum Beispiel, aber es ist nicht Stack-Zuweisung.

Wie kann ich meine Perversion-Aufgabe lösen, explizit mit der Stapelzuweisung und der C-Syntax in C#.

Das C# wurde nicht für solche Ziele erstellt und solche Features sind albern - ich weiß, aber die wichtigste Frage ist nicht über Signifikanz, es geht um solche Funktionen.

+0

Bitte post die vollständige Fehlermeldung, weil ich hoffe, dass es uns sagt * warum * es kann nicht so verwendet werden. – usr

+0

@usr scheint du hast mein Thema nicht gut gelesen :) Das Hauptproblem ist: "Aber ich war verwirrt, wenn ich keine Ausnahme/Fehler in diesem Programm gesehen habe." Ich habe keine Fehler erhalten, nur die Ausführung ohne Fehlermeldung. – Secret

+0

Sie sagen "C# Compiler sagt, dass in diesem Ausdruck Stackalloc nicht verwendet werden konnte.". Ist das nicht dein Hauptproblem? – usr

Antwort

5

Marc zeigte die Abhilfe, ich werde versuchen, warum dies erforderlich ist, zu erklären. Sie schreiben zwar unmanaged Code, aber die Methode ist immer noch eine verwaltete Methode. Es wird von IL in den Maschinencode kompiliert und seine Stack-Frame- und CPU-Register werden vom Garbage Collector nach Objektreferenzen durchsucht.

Der Jitter führt zwei wichtige Aufgaben, wenn es eine Methode kompiliert. Eins ist offensichtlich und gut sichtbar und übersetzt die IL in Maschinencode. Aber es gibt eine andere sehr wichtige Aufgabe und sie ist völlig unsichtbar, sie erzeugt Metadaten für eine Methode. Eine Tabelle, die angibt, welche Teile des Stapelrahmens Objektreferenzen enthalten und welche Teile Zeiger und Werttypwerte speichern. Und an diesen Stellen im Code speichert ein CPU-Register eine Objektreferenz. Auch an welcher Stelle im Methodencode eine Objektverweisung den Gültigkeitsbereich verlässt. Der Grund für GC.KeepAlive(), eine ziemlich einzigartige Methode, die überhaupt keinen Code erzeugt.

Der Garbage Collector benötigt diese Tabelle, um Objektverweise zuverlässig zu finden. Diese Tabelle hat jedoch nur eine Ebene der Indirektion. Er kann den Stack-Raum beschreiben, der für object_header reserviert ist, und den Pointer und den angezeigten Stack-Bereich als "nicht nach Objektreferenzen scannen" markieren. Es kann den Stapelspeicherbereich nicht beschreiben, wenn Sie object_header-> data direkt zuweisen. Es verfügt nicht über die zusätzliche Indirektion, den Stapel in kleinere Abschnitte zu unterteilen und Header zu beschreiben. Die Verwendung der lokalen Dummy-Variablen löst das Problem.

3

stackalloc möchte eine Variable zuweisen.Die folgenden Werke aber Sie müßten wirklich vorsichtig sein, dass aufzuheben, bevor die Methode verlassen - wenn Sie verlassen object_header->data Punkt auf eine Stelle in dem Stapel: schlechte Dinge:

int* ptr = stackalloc int[length]; 
    object_header->data = ptr; 

Die Tatsache, dass es muss zu einer lokalen variablen zugewiesen werden soll, die in der Beschreibung ausdrücklich:

für lokale variablen initializer:

...

stackalloc-initializer

stackalloc-Initialisierer:

stackallocunmanaged-Typ[Ausdruck]

+1

Sie heben die Zuweisung eines Stacks nicht auf. Es wird automatisch verworfen, wenn das Funktionsmember zurückkehrt. Siehe: http://msdn.microsoft.com/en-us/library/aa664785(v=vs.71).aspx –

+2

@AdrianCiura von deallocate, ich meine set 'object_header-> data' zu etwas anderem; Ich werde klären –