Статический анализ .NET Гарантированные вызовы функций в программе

Есть ли способ узнать все вызовы функций, которые будут выполняться как часть программы в мире С#?

Например, учитывая это:

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

Могу я сказать через FxCop или какую-то другую систему узнать CallTrueFunction?


person halivingston    schedule 06.04.2014    source источник
comment
Небольшое примечание: гарантировать слишком сильно, чтобы это можно было сделать (поищите программу остановки, если хотите знать, почему). Однако, безусловно, можно обнаружить функции, которые потенциально могут быть вызваны.   -  person Guvante    schedule 06.04.2014
comment
Вы можете охватить некоторые случаи, но, по крайней мере, не все. Возьмите функцию, которая принимает входные данные (файл, клавиатура) и имеет переключатель с 50 случаями на входе, и в каждом случае это новый вызов функции. Тогда это зависит от предоставленных данных.   -  person user743414    schedule 09.04.2014


Ответы (4)


Короткий ответ: нет.

Немного более длинный ответ — нет, ни для какой-либо нетривиальной программы на любом языке программирования.

Более длинный ответ заключается в том, что вы более или менее описываете проблему остановки. Не существует общего способа определить, какие методы достижимы, а какие нет, потому что для этого вам нужно решить проблему остановки.

Представьте себе цикл while, после которого идет единственный вызов myfunc(). myfunc() называется? Вы не можете знать, потому что цикл может или не может закончиться. Возможно, цикл зависит от переменной, переданной в функцию. Возможно, это зависит от ввода пользователя. В любом случае, если цикл завершается, вызывается myfunc(). Если цикл не прерывается, то myfunc() — мертвый код, который никогда не будет вызван. Скажем так, вы делаете while(Console.ReadLine() != "G") { }. Ваша программа вызывает myfunc()? Зависит от входа!

И, как и в случае с проблемой остановки, вы можете создавать тривиально маленькие программы, которые всегда выдают правильный ответ, или создавать очень маленькие конечные автоматы, которые всегда выдают правильный ответ. Но если вы затем возьмете свою программу статического анализа и запустите ее даже в относительно небольшом приложении, количество потенциальных комбинаций состояний быстро превысит количество доступных атомов во Вселенной.

Единственный способ узнать, будет ли ваша программа вызывать ту или иную функцию, — запустить ее и посмотреть, вызывает ли она ее. Затем вы можете сказать: «Для ввода X, в среде Y, на ЦП Z, в дату и время D, учитывая эти версии этих системных библиотек, в то время как система находилась под такой нагрузкой ЦП и такой нагрузкой ввода-вывода, и там, где колебания земли не прерывали работу жесткого диска, и где космический луч не переворачивал биты в памяти, моя программа называла подмножество G всех доступных функций F».

Если какая-либо из этих переменных изменится (входная будет основной), то ваш предыдущий анализ будет неполным.

Примечание. Невозможно даже дать строгие гарантии того, какие функции могут быть вызваны, потому что отражение может вызывать любую функцию, создавая строку (поэтому вы даже не можете сканировать имена функций), или даже генерировать и внедрять совершенно новые функции в ваша программа.

person russbishop    schedule 13.04.2014
comment
вы убедили меня --› void main() { while (true) { } functioncall(); } - person halivingston; 15.04.2014

В зависимости от того, чего вы хотите достичь, один из возможных способов — подойти к вещам с другой стороны и отметить/удалить все, что недоступно. С Resharper вы можете легко найти весь неиспользуемый код. Исходя из вашего примера, это будет означать:

else
{
    CallFalseFunction();
}

как недостижимый код. И он предложит вам изменить:

if (true)
{
    CallTrueFunction();
}

to:

CallTrueFunction();

После того, как вы очистили свой проект таким образом, все, что осталось, должно вызываться через некоторый путь выполнения, и все, что не зависит от условного параметра, должно быть вызвано (при условии, что программа не прерывается на полпути).

Это не поможет вам, когда вы пытаетесь найти, какие методы вызываются из определенной точки входа в вашем приложении с определенными параметрами. Если это то, что вы ищете, возможно, вы можете попробовать использовать профилировщик, способный регистрировать каждый вызываемый метод. Таким образом, вы зарегистрируетесь, чтобы получить список функций.

person Sam    schedule 09.04.2014
comment
Ваш пример работает. Но если этот код находится внутри функции, а логическое значение параметра функции перешлифовщик не может предложить никаких изменений. - person user743414; 09.04.2014
comment
Когда решение принимается каким-либо входом. - person user743414; 09.04.2014
comment
ни один из этих методов не является статическим. Мне нужно знать это во время анализа сборки/кода, а не во время выполнения. - person halivingston; 12.04.2014
comment
@user986697 user986697 Resharper выполняет все свои проверки по мере ввода/компиляции. Все, что не становится серым, должно каким-то образом вызываться (это не надежно, но работает довольно хорошо). Я не уверен, что можно сделать что-то еще с помощью чисто статических методов (см. ответ xenadu). - person Sam; 14.04.2014

Вы также можете использовать покрытие кода Visual Studio (если оно доступно в вашей версии).

http://msdn.microsoft.com/en-us/library/dd537628.aspx

person DanielCuadra    schedule 11.04.2014

Могут ли здесь помочь кодовые контракты? Если вы можете проверить состояние определенных значений логического теста в этом случае, сможете ли вы определить пути кода? Не массово au fait с ними. http://research.microsoft.com/en-us/projects/contracts/

person brumScouse    schedule 15.04.2014