Как скомпилировать проект C в Visual Studio 6 без необходимости использования LIBCD.lib?

Я собрал VolPack (https://graphics.stanford.edu/software/volpack/) как статическую библиотеку в Visual Studio 6 (под Windows XP), потому что я думаю, что она была создана для этого и не будет компилироваться в Visual Studio 2019. Но попытка написать программу на C++ в Visual Studio 2019 и ссылку на volpack .lib Я получаю сообщение об ошибке: Ошибка LNK1104 не может открыть файл «LIBCD.lib»

(Я не думаю, что это ошибка, характерная для VolPack, я думаю, что это относится к любой библиотеке, скомпилированной в VC 6, а затем связанной с более поздней версией VS, поэтому я думаю, что вопрос не слишком специфичен для StackOverflow.)

Я нашел это: https://support.microsoft.com/en-us/help/154753/description-of-the-default-c-and-c-libraries-that-a-program-will-link, что объясняет, почему он использует эту библиотеку, но я не знаю, что с этим делать в VS 6. Я не вижу возможности изменить многопоточность, чтобы заставить ее использовать другую библиотеку, и быстрый поиск в Google показывает, что VS 6 не поддерживает многопоточность.

Я нашел это: Как решить не удается открыть файл «LIBCD.lib» в Visual Studio 2008?, но я не уверен, что решение имеет отношение к моей проблеме, потому что строка «GLUI» нигде не встречается в библиотеке, на которую я пытаюсь ссылаться. Даже если это решение моей проблемы, я не знаю, где взять исходный код для GLUI, какие именно изменения мне нужно внести в make-файл или как заставить VS 6 использовать новый перекомпилированный GLUI, что бы это ни было. .

Следующее решение состояло в том, чтобы сказать компоновщику игнорировать LIBCD.lib, но это дало мне другие ошибки. Я нашел это: https://www.youtube.com/watch?v=zKrggjsgQx4, который в основном говорит игнорировать LIBCD.lib, а затем изменить библиотеку времени выполнения на многопоточную отладку, но это также дало мне ошибки.

Все ошибки, которые я получаю при попытке скомпилировать VolPack под VS 2019, представляют собой «потенциально унифицированную локальную переменную указателя», поэтому, вероятно, это какие-то простые модификации, чтобы заставить его скомпилировать под VS 2019, но я не эксперт в C, и я не знаю Я не хочу иметь дело с головной болью, пытаясь выяснить, как изменить программу и потенциально сломать ее. Итак, если кто-нибудь знает простой способ решения этой проблемы, который тоже может сработать. Спасибо.


person inhahe    schedule 10.06.2020    source источник
comment
Вы пишете C, но затем вы пишете C++. Затем вы снова пишете C. Который из них?   -  person Asteroids With Wings    schedule 11.06.2020
comment
Я не думаю, что вы сможете обойти эту ошибку.   -  person drescherjm    schedule 11.06.2020
comment
Напоминание: C== допускает перегрузку функций. Многие поставщики компиляторов используют изменение имен для разрешения перегруженных функций. Многие библиотеки C не учитывают искажение имени. Вот почему смешивание двух языков не рекомендуется.   -  person Thomas Matthews    schedule 11.06.2020
comment
Неразумно и влечет за собой проблемы пытаться использовать наборы компиляторов столь разных поколений для создания одной программы. Вместо того, чтобы пытаться сделать этот странный мэшап, я рекомендую сосредоточиться на том, чтобы все компилировалось с одной и той же версией VS — предположительно VS 2019.   -  person John Bollinger    schedule 11.06.2020
comment
Согласен, попробуйте скомпилировать в VS 2019. Это предупреждение компилятора C4703. У вас, вероятно, есть опция SDL для обработки всех предупреждений как включенных ошибок, что разумно. Из того, что я получаю, вам нужно инициализировать все унифицированные локальные переменные в nullptr или что-то более подходящее. С этого момента вы предоставлены сами себе.   -  person Visar    schedule 11.06.2020
comment
VС++ 6 полностью мертв. Он даже не компилирует С++ в том виде, в каком мы его знаем, поскольку он предшествует исходному стандарту.   -  person Asteroids With Wings    schedule 11.06.2020
comment
Рассмотрите возможность использования компилятора C++ GCC, возможно, как MinGW или установите дистрибутив Linux на свой ноутбук (например, Debian или Ubuntu...) после резервного копирования важных данных. Большинство систем Linux очень удобны для разработчиков. Скомпилируйте с g++ -Wall -Wextra -g (все предупреждения и отладочная информация). Обратите также внимание на Clang...   -  person Basile Starynkevitch    schedule 11.06.2020


Ответы (1)


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

Разница между 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
comment
Спасибо за ваш длинный и информативный ответ! Возможно, это не идеальная практика, но в итоге я решил проблему, просто скомпилировав библиотеку в VS 2015 вместо VS 2019. Я подумал, что если VS 6 не выдает ошибок, а VS 2019 выдает, возможно, есть промежуточная версия, которая не выдает ошибок, но достаточно современен, чтобы вызывать нужные библиотеки. Я не хотел тестировать каждую версию VS, чтобы увидеть, какая из них самая лучшая, которая не выдает ошибок, но потом я просто перешел на VS 2015, и это сработало, и я оставлю это на этом. Я добавлю этот ответ в закладки для дальнейшего использования. - person inhahe; 11.06.2020
comment
@inhahe звучит как хороший подход. Я обновил свой ответ некоторыми дополнительными ссылками о совместимости ABI между Visual Studio 2015/2017/2019, которые указывают, что статическая библиотека, скомпилированная с помощью Visual Studio 2015, должна быть совместима с скомпилированным кодом Visual Studio 2019. У меня сложилось впечатление, что примерно в VS 2015 Microsoft действительно начала работу над частью статического анализа своего компилятора. Я знаю, что количество предупреждений, которые я видел от VS 2005 до VS 2013, только увеличилось с переходом на VS 2015. Частично это было из-за новых функций безопасности, добавленных в стандартную библиотеку. - person Richard Chambers; 11.06.2020