2014-04-06 10 views
7

Gibt es eine Möglichkeit, alle Funktionsaufrufe, die als Teil eines Programms in C# Welt ausgeführt werden, zu finden?.NET Statische Analyse - Garantierte Aufrufe von Funktionen in einem Programm

Zum Beispiel gegeben dies:

static void Main(string[] args) 
{ 
    if (true) 
    { 
     CallTrueFunction(); 
    } 
    else 
    { 
     CallFalseFunction(); 
    } 
} 

Kann ich sagen, durch FxCop oder ein anderes System CallTrueFunction kennenlernen?

+1

Als eine kleine Notiz, garantiert ist zu stark, um getan zu werden (siehe das Halteprogramm, wenn Sie wissen wollen, warum). Es ist jedoch sicher möglich, Funktionen zu erkennen, die möglicherweise aufgerufen werden können. – Guvante

+0

Sie können einige Fälle abdecken, aber zumindest nicht alle. Nehmen Sie eine Funktion, die eine Eingabe (Datei, Tastatur) und einen Schalter mit 50 Fällen am Eingang hat und jeweils einen neuen Funktionsaufruf hat. Dann kommt es auf die gegebenen Daten an. – user743414

Antwort

10

Die kurze Antwort ist kein.

Die etwas längere Antwort ist nein, nicht für irgendein nicht-trivial Programm in irgendeiner Programmiersprache. Die längere Antwort ist, dass Sie mehr oder weniger the halting problem beschreiben. Es gibt keinen allgemeinen Weg zu bestimmen, welche Methoden erreichbar sind und welche nicht, weil Sie das Halteproblem lösen müssen.

Stellen Sie sich eine while Schleife und nach der Schleife ist der einzige Anruf an myfunc(). Wird myfunc() aufgerufen? Sie können nicht wissen, weil die Schleife beendet werden kann oder nicht. Vielleicht beruht die Schleife auf einer Variablen, die an die Funktion übergeben wird. Vielleicht ist es auf Eingaben des Benutzers angewiesen. Was auch immer der Fall ist, wenn die Schleife beendet wird, wird myfunc() aufgerufen. Wenn die Schleife nicht beendet wird, ist myfunc() ein ungültiger Code, der niemals aufgerufen wird. Lassen Sie uns einfach sagen, Sie tun while(Console.ReadLine() != "G") { }. Ruft Ihr Programm myfunc() auf? Hängt von der Eingabe ab!

Und ähnlich wie das Halteproblem können Sie trivial kleine Programme konstruieren, die immer die richtige Antwort produzieren, oder extrem winzige endliche Automaten erstellen, die immer die richtige Antwort produzieren. Aber wenn Sie dann Ihr statisches Analyseprogramm verwenden und es sogar auf einer relativ kleinen App ausführen, übersteigt die Anzahl der möglichen Zustandskombinationen schnell die Anzahl der verfügbaren Atome im Universum.

Die einzige Möglichkeit zu wissen, ob Ihr Programm diese Funktion oder diese Funktion aufrufen wird, ist es auszuführen und zu sehen, ob es funktioniert. Dann können Sie sagen "Für die Eingabe X, in der Umgebung Y, in der CPU Z, zur Datumzeit D, in Anbetracht dieser Versionen dieser Systembibliotheken, während das System unter dieser Menge an CPU-Last war, und diese Menge an I/O-Last, und wo Bodenvibrationen die Festplatte nicht unterbrachen und wo ein kosmischer Strahl keine Bits im Speicher umwandelte, nannte mein Programm die Teilmenge G aller verfügbaren Funktionen F ".

Wenn sich eine dieser Variablen ändert (die Eingabe ist die primäre), ist Ihre vorherige Analyse unvollständig.

Hinweis: Es ist nicht einmal möglich, starke Garantien dafür zu geben, welche Funktionen möglicherweise aufgerufen werden können, da Reflection jede Funktion aufrufen kann, indem sie eine Zeichenfolge erstellt (also nicht nach Funktionsnamen sucht) oder gar generieren und injizieren kann brandneue Funktionen in Ihrem Programm.

+0

* klatscht * gut gemacht Herr, gut gemacht – iamkrillin

+0

Sie überzeugten mich mit -> void main() {while (true) {} functioncall(); } – halivingston

2

Je nachdem, was Sie erreichen möchten, ist eine Möglichkeit, Dinge in die entgegengesetzte Richtung zu bewegen und alles zu markieren/entfernen, das nicht erreicht werden kann. Mit Resharper können Sie einfach all unused code finden. An Ihrem Beispiel würde dies markieren:

als unerreichbaren Code. Und es wird vorschlagen, dass Sie ändern:

if (true) 
{ 
    CallTrueFunction(); 
} 

zu:

CallTrueFunction(); 

Nachdem Sie Ihr Projekt auf diese Weise, alles gereinigt haben sich noch vorfindet sollte durch einige Ausführungspfad aufrufbar sein und alles, was nicht auf eine Berufung bedingter Parameter sollte aufgerufen werden (vorausgesetzt, das Programm bricht nicht auf halbem Wege ab).

Dies hilft Ihnen nicht, wenn Sie herausfinden möchten, welche Methoden von einem bestimmten Einstiegspunkt in Ihrer App mit bestimmten Parametern aufgerufen werden. Wenn Sie das suchen, können Sie vielleicht versuchen, einen Profiler zu verwenden, der jede aufgerufene Methode protokollieren kann. Auf diese Weise erhalten Sie bei der Protokollierung die Liste der Funktionen.

+0

Ihr Beispiel funktioniert. Aber wenn dieser Code innerhalb einer Funktion ist und der boolesche Parameter reSharper kann keine Änderung vorschlagen. – user743414

+0

Wenn die Entscheidung von einer Eingabe getroffen wird. – user743414

+0

keine dieser Techniken sind statisch. Ich muss dies zur Build/Code-Analysezeit wissen, nicht zur Laufzeit. – halivingston