Unreachable code in C# for loop – intelligenter compiler

Hallo,

kürzlich hat mich Microsofts C# compiler mit seiner intelligenten Analyse verblüfft. Ich hatte sinngemäß folgenden code geschrieben:

for (int jj = 0; jj < parts.Length - 1; ++jj)
{
    part = parts[jj];
    int count = result.getRefCount(refAttr);
    for (int ii = 0; ii < count; ++ii)
    {
        EOInstance packagedElement = result.getRefObject(refAttr, ii);
        if (packagedElement.getValue("Name") == part)
        {
            result = packagedElement;
            continue;
        }

    }
    string msg = "Cannot resolve path '" + parts.ToString() +
                     "' for attribute '" + refAttr + ". Unknown part is '" +
                     parts + "'.";

    throw (new Exceptions.UnknownPathException(msg));
}

Der C# compiler meldete:

Fehler CS0162: Warnung als Fehler: Unerreichbarer Code wurde entdeckt.

und die IDE markierte die Inkrement-Anweisung ‘++jj in der äußeren for-Schleife.

Nach konzentrierter Durchsicht des codes ist mit der Fehler aufgefallen: die throw Anweisung sollte in die innere Schleife verschoben werden. So wie der code geschrieben war, wurde die äußere Schleife tatsächlich nur einmal durchlaufen und die Inkrement-Anweisung nie ausgeführt da immer am Ende des ersten Durchlaufs eine exception geworfen wurde.

Der C++ compiler von Visual Studio findet dieses Problem nicht, auch nicht im release build (wo der compiler weitergehende semantische Prüfungen machen kann unter Ausnutzung der Analyse-Ergebnisse des optimizers).

UnreachableCode - 0 Fehler, 0 Warnung(en)
==== Erstellen: 1 erfolgreich, Fehler bei 0, 0 aktuell, 0 übersprungen ====

Bleibt noch die Frage, was PC-Lint (das ich seit mehr als 10 Jahren für alle C++-Entwicklungen verwende) zu der Sache meint.
Enttäuschenderweise meldet es diesen Fehler auch nicht, nicht mal mit zwei Durchläufen (-passes(2)):

PC-lint for C/C++ (NT) Vers. 8.00w, Copyright Gimpel Software 1985-2007

--- Module:   UnreachableCode.cpp (C++)

/// Start of Pass 2 ///

--- Module:   UnreachableCode.cpp (C++)

--- Global Wrap-up

error 900: (Note -- Successful completion, 0 messages produced)

Für diese Test habe ich folgenden mutmaßlich äquivalenten code verwendet:

        for (int jj = 0; jj < 10; ++jj)
	{
		for (int ii = 0; ii < 10; ++ii)
		{
			if (ii == 5)
			{
				continue;
			}
		}

		throw(std::exception("Huh"));
	}

Also wirklich eine beeindruckende Leistung des C# compilers.

Der code enthält übrigens noch einen weiteren logischen Fehler, auf den ich erst durch die Meldung des C# compilers aufmerksam wurde, was aber für die Intention dieses postings nicht relevant ist.

Viele Grüße,
Andreas

Technorati Tags: , , ,

Nachtrag vom 04.05.2008: ein kluger Kollege hat mich darauf hingewiesen, dass Microsoft Visual C++ bei Verwendung von warning level 4 den gewünschten Hinweis tatsächlich meldet. Für meine Produktionssoftware verwende ich /W4, für das kleine Beispielprogramm habe ich es aber bei den defaults belassen.

One Response to “Unreachable code in C# for loop – intelligenter compiler”

  1. Andreas Awenius’ blog » Blog Archive » C# Compiler Kauderwelsch Says:

    [...] ich hatte mich ja kürzlich über die Qualität des Microsoft C#-compilers positiv geäußert. [...]

Leave a Reply