2014-04-06 4 views
7

C'è un modo per scoprire tutte le chiamate di funzione che verranno eseguite come parte di un programma nel mondo C#?Analisi statica .NET - Chiamate garantite alle funzioni in un programma

Per esempio, dato questo:

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

posso dire attraverso FxCop o qualche altro sistema per conoscere CallTrueFunction?

+1

Come nota minore, la garanzia è troppo forte per essere eseguita (cercare il programma di interruzione se si desidera sapere perché). Tuttavia è certamente possibile rilevare funzioni che potrebbero essere potenzialmente chiamate. – Guvante

+0

Puoi coprire alcuni casi ma almeno non tutti. Prendi una funzione che prende un input (file, tastiera) e ha un interruttore con 50 casi sull'input e in ogni caso è una nuova chiamata di funzione. Quindi dipende dai dati forniti. – user743414

risposta

10

La risposta breve è no .

La risposta leggermente più lunga è no, non per qualsiasi programma non banale in qualsiasi linguaggio di programmazione.

La risposta più lunga è che stai descrivendo the halting problem più o meno. Non esiste un modo generale per determinare quali metodi sono raggiungibili e quali no perché, per farlo, è necessario risolvere il problema dell'arresto.

Immaginate un ciclo while e dopo il ciclo è l'unica chiamata a myfunc(). myfunc() chiamato? Non puoi sapere perché il ciclo può o non può terminare. Forse il ciclo si basa su una variabile passata nella funzione. Forse si basa sull'input dell'utente. In ogni caso, se il ciclo termina, viene chiamato myfunc(). Se il ciclo non termina, allora myfunc() è un codice morto che non verrà mai chiamato. Diciamo che lo fai while(Console.ReadLine() != "G") { }. Il tuo programma chiama myfunc()? Dipende dall'input!

E proprio come il problema dell'arresto, è possibile costruire piccoli programmi banali che producono sempre la risposta corretta o creare macchine a stati finiti estremamente piccoli che producono sempre la risposta corretta. Ma se poi prendi il tuo programma di analisi statico e lo esegui anche su un'app moderatamente piccola, il numero di potenziali combinazioni di stati supera rapidamente il numero di atomi disponibili nell'universo.

L'unico modo per sapere se il programma chiamerà questa funzione o quella funzione è eseguirlo e vedere se lo fa. Quindi puoi dire "Per l'input X, nell'ambiente Y, sulla CPU Z, alla data D, date queste versioni di queste librerie di sistema, mentre il sistema era sotto questa quantità di carico della CPU, e questa quantità di carico I/O, e dove le vibrazioni del terreno non hanno interrotto l'hard disk, e dove un raggio cosmico non ha gettato alcun bit in memoria, il mio programma ha chiamato il sottoinsieme G di tutte le funzioni disponibili F ".

Se una di queste variabili cambia (l'input è quello primario), l'analisi precedente è incompleta.

Nota: non è nemmeno possibile fornire forti garanzie su quali funzioni potrebbero essere chiamate perché la riflessione può chiamare qualsiasi funzione costruendo una stringa (in modo che non si possa nemmeno cercare nomi di funzioni), o anche generare e iniettare nuove funzioni nel tuo programma.

+0

* applausi * ben fatto signore, ben fatto – iamkrillin

+0

mi hai convinto con -> void main() {while (true) {} functioncall(); } – halivingston

2

A seconda di ciò che si desidera ottenere, un modo possibile è quello di affrontare le cose al contrario e contrassegnare/rimuovere tutto ciò che non può essere raggiunto. Con Resharper puoi facilmente trovare all unused code. Seguendo il tuo esempio, questo segnerebbe:

else 
{ 
    CallFalseFunction(); 
} 

come codice irraggiungibile. E ti suggerisce di cambiare:

if (true) 
{ 
    CallTrueFunction(); 
} 

a:

CallTrueFunction(); 

Dopo aver pulito il vostro progetto in questo modo, tutto ciò che è rimasto dovrebbe essere richiamabile attraverso alcuni percorso di esecuzione e tutto ciò che non potendo contare su un il parametro condizionale dovrebbe essere chiamato (supponendo che il programma non abortisca a metà).

Questo non ti aiuterà quando cerchi di trovare quali metodi sono chiamati da un punto di ingresso specifico nella tua app con parametri specifici. Se questo è ciò che stai cercando, forse puoi provare a cercare di utilizzare un profiler in grado di registrare ogni metodo chiamato. In questo modo la registrazione ti darà l'elenco delle funzioni.

+0

Il tuo esempio funziona. Ma se quel codice si trova all'interno di una funzione e il booleano di un parametro di configurazione del processo non può suggerire alcuna modifica. – user743414

+0

Quando la decisione è presa da qualche input. – user743414

+0

nessuna di queste tecniche è statica. Ho bisogno di sapere questo al tempo di analisi build/code, non in fase di runtime. – halivingston