Как мы можем обнаружить все сравнения указателей в исходном коде? Переполнение стека

Мы хотим найти все сравнения указателей из типа класса. Например, у нас есть класс A и производные классы от A, такие как B, C ect.

A *pa;
A *pa2;
B *pb;

Все сравнения, такие как if (pa == pa2) или if (pa! = Pb), должны быть найдены в нашем исходном коде.

Я знаю, что мы можем использовать анализатор CLang, чтобы найти эти сравнения, но наш исходный код не совместим с CLang. Мы используем visual studio 2015.

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

У кого-нибудь есть решение, чтобы найти его? Инструмент, такой как CppCheck (который проверяет возможные ошибки) или расширение Visual Studio?

Редактировать:

Кто-нибудь знает, как я могу найти все сравнения в моем коде с синтаксисом CppDepend / CQLinq? Это также может помочь мне. CppDepend использует CLang, но продолжает анализировать, если он имеет ошибки синтаксического анализа.

2

Решение

наш DMS Software Reengineering Toolkit с этими C ++ 14 интерфейс может быть использован для этого.

DMS — это механизм анализа и преобразования программ общего назначения, который можно настраивать для достижения желаемого влияния на язык программирования, предоставляемый ему в качестве подключаемого модуля. Его интерфейс C ++ 14 конфигурируемо обрабатывает чистый ANSI, синтаксис в стиле GCC / Clang или синтаксис Visual Studio. Включает в себя полный препроцессор.

Для достижения цели ОП необходимо настроить DMS на:

  1. Разбираем единицы компиляции, которые выдают AST.
  2. для каждого модуля компиляции выполните разрешение имени и типа. Это создает таблицы символов, содержащие информацию о типе, и обеспечивает основу
    для вычисления типов произвольных выражений. Эта возможность
    встроенный в интерфейс DMS C ++.
  3. сканировать AST, искать операторов == и! =
  4. попросить DMS вычислить тип правого и левого подвыражений
  5. Убедитесь, что этот тип был целевым классом или тот, который наследуется от целевого класса. (Предположительно целевой класс идентифицируется как определенный в определенной исходной позиции файла / строки; это можно найти с помощью поиска в таблице символов. Проверка, является ли тип производным от другого, является просто вопросом рекурсивного поиска, возможно, нескольких записанных родительских ссылок. для ссылок таблицы символов, чтобы проверить, является ли родительский тип желаемым целевым типом).
  6. Сообщите имя файла, исходную строку и столбец оператора.

Каждый из вышеперечисленных шагов поддерживается напрямую механизмами / API, предоставляемыми DMS и внешним интерфейсом C ++ 14. Вероятно, для достижения эффекта требуется пара страниц пользовательского кода, добавленного в DMS.

2

Другие решения

Мое решение: (как сказал @ M.M) обернуть указатели классом обертки шаблона, который реализует перегрузки операторов, такие как -> * (так меньше проблем с компиляцией) и удаляет операторы сравнения, такие как == != (так что найдите сравнения с ошибками компиляции). Замена всех указателей может быть сделано с помощью регулярного выражения. (A * с A_Wrapper)

Я также обнаружил, что использование указателя на карте похоже на сравнение указателей. Если вы используете указатели на карте, вы также должны удалить <-Оператор в вашем классе оболочки.

Конечно, у меня были ошибки компиляции, но эти ошибки было нетрудно решить. И кажется, что это определенное решение.

Надеюсь, это кому-нибудь поможет.

0

Я предполагаю, что пропускаю вопрос. Таким образом, вы просто хотите найти все экземпляры любого указателя, указывающего на тип A, B, C и т. Д., Где указатель используется в условном выражении для сравнения …

Итак, вы знаете все имена типов. Это означает, что существует конечное число типов и конечное число сравнений, например ==! = <=> = < > Верно?

Поэтому для каждого экземпляра указателя, созданного всеми типами, создайте таблицу. Это дает вам кодированное имя каждого указателя, который вы ищете.

Фред * Майфред, * Вашфред, * thefred;

учетная запись * primaryacct, * secondacct;
… и так далее…

Ваш стол будет:
myfred
yourfred
thefred
primaryacct
secondacct

Теперь для каждого экземпляра каждого — начиная с первого «myfred», найдите myfred, затем ==, затем! = И т. Д. (Поглощая все пробелы), когда вы найдете первый (левая сторона comaprison, например,

secondacct<знак равно

затем найдите правую часть) и сравните его с каждым кодированным именем указателя в созданной вами таблице. Когда у вас есть совпадение, подобное myfred! = Primaryacct, вы делаете с ним то, что вам нравится. Скажем так, ради аргументов: вы хотите выполнить глобальный поиск и замену для данного сравнения или списка сравнений, вы можете сделать это на ходу, открыв дополнительный файл для вывода, а также прочитав и найдя каждый из них. В этом случае вы можете вывести его в свою пользу в новый файл исходного кода.

По сути, просто найдите каждое сравнение, посмотрите на каждую его сторону и посмотрите, есть ли у обеих сторон закодированное имя в вашей таблице. По сути, вы просто анализируете код, используя одну и ту же таблицу идентификаторов по обе стороны конечной комбинации строк сравнения — опять же, они: [==! = <=> = < >]

Я не знаю программного инструмента, который бы это делал, но вы могли бы просто написать это довольно быстро. Конечно, это послужило бы только одной этой цели, но сделало бы работу быстро.

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

Чтобы получить целую строку кода при чтении в —

В Си — просто используйте fgets

В C ++ — используйте getline

Затем просто проанализируйте буфер, который вы прочитали, с помощью логики, описанной выше.

————— Отредактировано ————— относительно комментариев ниже

@ YusufRamazanKaragöz — Дуб — я прошу прощения за чрезмерное обобщение. Есть ли шанс, что вы могли бы предоставить пример кода, который включает в себя несколько таких вопросов — например, что если он охватывает несколько строк? Я основывал свой мыслительный процесс на том, что вы написали: «Все сравнения, такие как if (pa == pa2) или if (pa! = Pb), должны быть найдены в нашем исходном коде», и ничего более, поэтому я не стал расширяться до возврата функций, и т.д. Что касается построения таблицы — вы знаете правильные типы? Таким образом, для каждой строки, в которой есть переменная, объявленная для этих типов, вы должны ее построить. Например, если бы я хотел таблицу каждой переменной, определенной в каждой строке кода для всех файлов программы, — я бы искал во всех строках слово char. Затем после этой строки я буду искать строки, разделенные запятыми, пока не будет запятых или точек с запятой (которые могут перейти к следующей строке, поэтому используйте fgetc вместо fgets). Некоторые из этих объявлений были бы прямыми, некоторые могли бы быть * char, некоторые char [] — и т. Д. Тогда у меня был бы список каждой переменной типа char. Я имею в виду, что если вы выполняете поиск по имени типа, о котором говорите, разве вы не видите строку, в которой он встречается, и все, что объявлено после него? Если вы можете, то вы можете построить индексную таблицу. Или есть какая-то причина, по которой я не понимаю, почему это нельзя сделать? Поиск приведенных значений создает еще один набор правил синтаксического анализа и еще больше усложняет задачу, как и сравнение шаблонов с объектами. Я до сих пор не понял твою дилемму из первоначального вопроса. Я действительно хочу помочь, но, возможно, блок кода, который охватывает каждую парадигму анализа, поможет мне определить, смогу ли я. На самом деле, если бы вы могли дать мне представление о том, почему вы вообще хотите это сделать, это помогло бы мне лучше мыслить. Хотите ли вы что-то глобально изменить? Я, конечно, отложу ваше решение и перестану пытаться, если вы считаете, что усилия напрасны. Спасибо за ваше время, однако, терпение, и я надеюсь, что вы найдете решение.

-2
По вопросам рекламы [email protected]