Frage

In C ++ gibt es viele Möglichkeiten, wie Sie Code schreiben können, den Sie kompilieren, aber ergeben undefiniertes Verhalten (Wikipedia). Gibt es etwas Ähnliches in C#? Können wir Code in C# schreiben, das kompiliert, aber undefiniertes Verhalten hat?

War es hilfreich?

Lösung

Wie andere erwähnt haben, kann so ziemlich alles im "unsicheren" Block "unsicher" implementierende Verhaltensweisen erzielen. Durch den Missbrauch unsicherer Blöcke können Sie die Code Bytes ändern, aus denen die Laufzeit selbst besteht, und daher sind alle Wetten ausgeschaltet.

Der Eckfall der Integer Division hat ein implementierungsdefiniertes Verhalten.

Wenn Sie eine Ausnahme auswerfen und sie nie fangen, wird das implementierungsdefinierte Verhalten geführt-den Prozess beenden, einen Debugger starten und so weiter.

Es gibt eine Reihe anderer Situationen in C#, in denen wir gezwungen sind, Code zu emittieren, das implementiert ist. Zum Beispiel diese Situation:

http://blogs.msdn.com/ericlippert/archive/2006/04/06/odious-ambiguous-overloads-part-two.aspx

Die Situationen, in denen ein sicheres, gut erzogenes C# -Programm implementiert, sollte jedoch sehr selten sein.

Andere Tipps

Ja! Es gibt auch in einem sicheren Kontext! (Nun, es ist die Implementierung definiert, zumindest nicht definiert zu sein)

Hier ist einer von Marek Safar und Vsadov in der Roslyn ProblemeEs gibt ein Missverhältnis zwischen C# und der CLI in Bezug auf bool.

C# glaubt, dass es nur eine Art von Art von gibt true, und eine Art von false.

CLI glaubt das false ist ein Byte mit 0 und alle anderen Werte sind true.

Diese Diskrepanz bedeutet, dass wir C# zwingen können, um dies zu tun etwas a (geringfügig) interessant Dinge Ding:

//non-standard bool
//We're setting a bool's value to a byte value of 5.
var a = new bool[1];
Buffer.SetByte(a, 0, 5);

//non-standard bool
//We're setting a bool's value to a byte value of 10.
var b = new bool[1];
Buffer.SetByte(b, 0, 10);

//Both are true.
Console.WriteLine(a[0]);
Console.WriteLine(b[0]);

//But they are not the same true.
Console.WriteLine(a[0] == b[0]);

Die obigen Ausgaben:

true

true

false

Interessanterweise ist der Debugger anderer Meinung (muss die Wahrheit anders bewerten?)

enter image description here

Wie auch immer, in der Schlussfolgerung, zu der das C# -Team gekommen zu sein scheint, ist (Hervorhebung hinzugefügt):

Dh die Sprache wird völlig unbeteilig über nicht standardmäßige Bools bleiben. Die bestimmte Implementierung (wie in MS C# auf CIL) wird die Existenz von nicht standardmäßigen Bools anerkennen und ihr Verhalten als angeben nicht definiert

Wenn man sich das Wiki ansieht, sind die Situationen, in denen undefiniertes Verhalten stattfindet, entweder nicht zulässig oder aus einer Ausnahme in C#.

In unsicherem Code ist das undefinierte Verhalten, das ich jedoch für möglich halte, da, da Sie Zeiger usw. verwenden können.

EDIT: Es sieht so aus, als hätte ich Recht: http://msdn.microsoft.com/en-us/library/aa664771%28vs.71%29.aspx

Hat ein Beispiel für undefiniertes Verhalten in C#

Nach dem ECMA-334-Dokument (S. 473):

Ein Programm, das keine Vorkommen des unsicheren Modifikators enthält, kann kein undefiniertes Verhalten aufweisen.

Das fördert "implementierende" zum schlimmsten Fall, siehe Eric Lipperts Antwort.

Viele und Unterprogramme haben Anforderungen, die als:

  1. Wenn Sie gültige Daten angegeben haben, erstellen Sie eine gültige Ausgabe.

  2. Lagern Sie sich nicht in Bezug auf ungültige Inputs, wenn Sie die Nuklearraketen starten oder die Gesetze von Zeit und Kausalität negieren.

Eines der wichtigsten Designziele von Java- und .NET -Sprachen ist, dass der Code, sofern Code nicht sicher ist, die als "unsicher" gekennzeichnet sind Finalize Kann aus der Sicht des Zeit-/Kausalität etwas seltsam sein, diese können als Ausnahmen von normalen Regeln der Kausalität und nicht als totaler Widerruf bezeichnet werden. Diese Situation unterscheidet sich stark von der Situation in C, in der viele Arten von datenabhängigen Fehlern (z. B. Überlauf des Ganzzahl) dazu führen können, dass Compiler sich auf willkürliche Weise verhalten, einschließlich der Annahmen, die erforderlich wären, um Überlauf zu vermeiden. Die wirklich schrecklichen Arten von undefiniertem Verhalten, die in der hypermodernen C -Philosophie ermutigt werden, gibt es in C# oder anderen .NET -Sprachen außerhalb von "unsicheren" Blöcken nicht.

Nicht wirklich im genauen Wiki -Sinne, aber ich nehme an, das offensichtlichste Beispiel, das mir in den Sinn kommt, ist einfach, einen Thread -Code zu schreiben, aber dann ist es in jeder Sprache so.

Im Allgemeinen würde ich nein sagen.

Verwenden Sie die automatische Variable, bevor Sie initialisiert werden.

Alle Variablen müssen initialisiert werden. Wenn nicht eine Ausnahme auftritt.

Durch Null teilen

Ausnahme wird ausgelöst.

Indexierung eines Arrays außerhalb der Grenzen

Ausnahme wird ausgelöst

Wie Aequitarum Custos darauf hinwies, können Sie einen unsicheren Code verwenden. Andererseits ist dies nicht wirklich C#, Sie entscheiden sich ausdrücklich aus der C# -E -Umgebung.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top