Когда вы используете статическую библиотеку, которая имеет зависимости от других библиотек, компилятор будет жаловаться, если не сможет найти эти другие библиотеки.
Разница между Microsoft Visual Studio 6.x и Visual Studio 2019 огромна. Поскольку я перенес старый код, как C, так и C++, с 6.x на VS 2015, мне пришлось внести ряд изменений в исходный код, чтобы компиляции могли работать из-за улучшений Microsoft в соблюдении стандартов. как поддержка новых версий стандартов, некоторые из которых устарели ранее поддерживаемые конструкции.
См. этот пост о совместимости между версиями, совместимость библиотеки ABI между версиями Visual Studio См. также:
Двоичная совместимость между VS2017 и VS2015
ABI-совместимость c-библиотек Visual Studio
И это сообщение в блоге Microsoft о выпуске Visual Studio 2019 от 2019 года говорит:
Теперь доступна Visual Studio 2019 версии 16.0, которая совместима с VS 2015/2017 в двоичном виде. В этом первом выпуске VS 2019 мы реализовали больше функций компилятора и библиотеки из рабочего документа C++20, реализовали больше перегрузок («последний босс» C++17) и исправили многие проблемы с правильностью, производительностью и пропускной способностью. . Вот список функций компилятора/библиотеки C++17/20 и исправлений библиотеки. (Как обычно, многие ошибки компилятора также были исправлены, но они не перечислены здесь; исправления компилятора, как правило, связаны с определенными загадочными шаблонами кода. страница об улучшениях соответствия компилятора в VS 2019.)
Я не вижу другого выхода, кроме как работать с исходным кодом, чтобы сделать его совместимым с Visual Studio 2019. Если вы посмотрите, вы можете обнаружить, что вашего уровня знаний C достаточно для реализации некоторых из приведенных ниже предложений.
Казалось бы, лучший способ действий — внести необходимые изменения в исходный код библиотеки, чтобы она правильно скомпилировалась в Visual Studio 2019.
Лучше всего просмотреть исходный код в каждом месте, где обнаружена ошибка неинициализированного указателя, и исправить исходный код, чтобы ошибка больше не возникала. Программисты, которые ранее работали в этих областях кода, очевидно, не учитывали потенциальный поток управления, вероятно, из-за их ожидания того, что отсутствующий код никогда не будет выполнен, исходя из предположений о том, как будет использоваться функция. Скорее всего, любые такие функции сложны и могут нуждаться в рефакторинге.
Чаще всего я видел этот тип отсутствующего потока из-за того, что оператор switch
пропускал default:
для захвата события, когда переменная switch
не является одним из указанных значений case. Это также может быть связано с оператором if
, который представляет собой серию else if
без конечного else
для захвата любого другого возможного условия. Или это также может быть связано с циклом, который имеет оператор break
перед инициализацией переменной-указателя или который использует оператор continue
для пропуска места инициализации переменной.
В большинстве случаев эти проблемы связаны с функциями с низкой связностью и/или слишком сложными и большими действиями по обслуживанию с течением времени, вызывающими такого рода проблемы.
Менее желательной практикой для ошибки потенциально неинициализированного указателя является просто инициализация с некоторым подходящим значением. Вы можете перейти к месту ошибки, щелкнуть переменную и перейти туда, где она определена, а затем установить для нее соответствующее значение. В большинстве случаев значение NULL
для указателей является самым безопасным, потому что, если оно останется NULL
и будет использоваться без изменения до правильного значения, ваше приложение должно аварийно завершить работу, сообщая вам о наличии проблемы.
Инициализируя NULL
, вы предполагаете, что предыдущие программисты знали, что они делали, и возможные потоки, обнаруженные компилятором, которые оставили бы переменную неизменной до правильного значения, никогда не произойдет из-за логики.
И если произойдет поток неинициализированных указателей, вы узнаете, когда приложение вылетит. К сожалению, отследить причину сбоя может быть сложно.
Вы можете использовать assert
и другие тесты в коде для создания точки останова при отладке или для генерации исключения, если это C++, что может быть более информативным, чем просто сбой. Таким образом, добавление такого теста непосредственно перед строкой исходного кода, вызывающей ошибку, может быть полезным для проверки NULL
в тесте перед использованием указателя.
Или, если у функции есть код состояния, указывающий, сработала она или нет, и любые ошибки вместе с каким-либо способом возврата статуса ошибки, тогда наиболее эффективным было бы использование этого сообщения об ошибке в указателе, где генерируется потенциально неинициализированная ошибка указателя. если проверка работоспособности не удалась.
Однако, если вы можете определить безопасное значение по умолчанию, вы можете использовать его вместо этого. Определение безопасного значения потребует просмотра исходного кода, чтобы определить, каким должно быть безопасное значение по умолчанию. Иногда таким безопасным значением может быть адрес переменной соответствующего типа, инициализированной нулем.
Предупреждение: если возвращается адрес в указателе, не используйте адрес локальной переменной для функции. Когда функция возвращает значение, этот адрес больше не будет действительным, что приведет к неопределенному поведению.
Предупреждение 2: если ожидается, что адрес в указателе будет выделен с использованием malloc()
или new
или аналогичного распределителя памяти, вы должны использовать тот же механизм, чтобы, когда какой-либо код решает освободить память с помощью free()
или delete
тогда все получится.
Этот обзор потребует прочтения исходного кода функции, в которой используется неинициализированный указатель, если значение указателя локализовано в самой функции. Если указатель возвращается функцией, а значение экспортируется функцией пользователю функции, вам также потребуется просмотреть исходный код, в котором функция используется, чтобы определить соответствующее значение по умолчанию.
Итак, что я предлагаю вам сделать, так это то, что в каждом месте, где вы выполняете инициализацию, вы добавляете уникальный идентифицирующий комментарий (что-то вроде строк «Inhahe fix uninitialized pointer error 06/10/2020») к строке, чтобы вы могли затем сделать поиск, чтобы найти их позже, а затем вернуться к проблемному коду и фактически исправить ошибку компилятора путем рефакторинга или изменения кода, чтобы устранить возможную ошибку неинициализированного указателя.
И прежде чем что-либо делать, поставьте исходный код под какой-либо контроль версий.
person
Richard Chambers
schedule
11.06.2020
g++ -Wall -Wextra -g
(все предупреждения и отладочная информация). Обратите также внимание на Clang... - person Basile Starynkevitch   schedule 11.06.2020