【问题标题】:How do I compile a C project in Visual Studio 6 without it needing LIBCD.lib?如何在不需要 LIBCD.lib 的情况下在 Visual Studio 6 中编译 C 项目?
【发布时间】:2020-06-10 21:50:00
【问题描述】:

我已将 VolPack (https://graphics.stanford.edu/software/volpack/) 编译为 Visual Studio 6(在 Windows XP 下)中的静态库,因为我认为这就是它的用途,它不会在 Visual Studio 2019 下编译。但尝试编写Visual Studio 2019 中的 C++ 程序并链接到 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 中如何处理它。我没有看到关于多线程的选项以使其使用不同的库,快速谷歌搜索显示 VS 6 不支持多线程。

我确实找到了这个:How to solve "cannot open file 'LIBCD.lib' " in visual studio 2008?,但我不确定该解决方案是否与我的问题相关,因为字符串“GLUI”没有出现在我试图链接到的库中。即使它是我的问题的解决方案,我也不知道从哪里获得 GLUI 的源代码,我需要对 makefile 进行哪些更改,或者如何使 VS 6 使用新的重新编译的 GLUI,不管是什么.

下一个解决方案基本上是告诉链接器忽略 LIBCD.lib,但这给了我其他错误。我发现了这个:https://www.youtube.com/watch?v=zKrggjsgQx4,它基本上说忽略 LIBCD.lib,然后将运行时库更改为多线程调试,但这也给了我错误。

尝试在 VS 2019 下编译 VolPack 时遇到的错误都是“可能统一化的局部指针变量”,因此可能需要进行一些简单的修改才能使其在 VS 2019 下编译,但我不是 C 和专家我不想处理试图弄清楚如何修改程序并可能破坏它的头痛。因此,任何人都知道解决该问题的简单方法,该方法也可能有效。谢谢。

【问题讨论】:

  • 你写的是 C,然后你写的是 C++。然后你再写C。是哪一个?
  • 我认为您无法解决此错误。
  • 提醒:C== 允许函数重载。许多编译器供应商使用 name mangling 来解析重载函数。许多 C 库不考虑名称修饰。这就是为什么不建议混合使用两种语言的原因。
  • 尝试使用不同代的编译器套件来尝试构建一个程序是不明智的并且会带来麻烦。我建议不要尝试制作这种奇怪的混搭,而是专注于让所有内容都使用相同版本的 VS 进行编译——大概是 VS 2019。
  • VC++ 6 完全死了。它甚至不编译我们所知道的 C++,因为它早于原始标准。

标签: c++ c visual-studio visual-studio-2019 visual-studio-6


【解决方案1】:

当您使用依赖于其他库的静态库时,如果找不到其他库,编译器会报错。

Microsoft Visual Studio 6.x 和 Visual Studio 2019 之间的差异是巨大的。由于我已将 C 和 C++ 的旧代码从 6.x 移植到 VS 2015,因此我不得不对源代码进行一些更改以允许编译工作,因为 Microsoft 在遵守标准方面也有所改进支持新版本的标准,其中一些已弃用以前支持的结构。

请参阅这篇关于版本之间兼容性的帖子,Library ABI compatibility between versions of Visual Studio 另请参阅:

Binary compatibility between VS2017 and VS2015

ABI-Compatibility of visual studio c-libraries

这个日期为 2019 年的 blog posting from Microsoft about the release of Visual Studio 2019 说:

Visual Studio 2019 16.0 版现已推出,并且兼容二进制 与 VS 2015/2017。在 VS 2019 的第一个版本中,我们实现了 来自 C++20 工作论文的更多编译器和库功能, 实现了更多的重载(C++17 的“最终boss”),并且 修复了许多正确性、性能和吞吐量问题。这是一个 C++17/20 编译器/库功能工作和库列表 修复。 (和往常一样,也修复了许多编译器错误,但不是 此处列出;编译器修复往往特定于某些神秘代码 模式。我们最近发布了关于编译器优化和构建的博客 VS 2019 中的吞吐量改进,我们维护了一个文档 有关 VS 2019 中编译器一致性改进的页面。)

除了使用源代码使其与 Visual Studio 2019 兼容之外,我没有看到任何其他方法。如果您看一下,您可能会发现您的 C 专业水平足以实施以下一些建议.

最好的做法似乎是对库进行必要的源代码更改,以便在 Visual Studio 2019 下正确编译。

最好的做法是检查每个发现未初始化指针错误的地方的源代码并更正源代码,以便不再生成错误。以前在这些代码领域工作的程序员显然遗漏了潜在的控制流,这可能是因为他们期望永远不会基于函数使用方式的假设来执行丢失的代码。很可能任何此类功能都很复杂,可能需要重构。

我经常看到这种类型的缺失流是由于switch 语句缺少default: 来捕获switch 变量不是指定案例值之一的事件。这也可能是由于if 语句是一系列else if 而没有最终else 来捕获任何其他可能的条件。或者也可能是由于在初始化指针变量之前有一个break 语句的循环,或者它使用continue 语句跳过了变量的初始化位置。

在大多数情况下,这些问题是由于功能内聚力低和/或过于复杂和庞大,随着时间的推移维护操作会引入此类问题。

对于可能未初始化的指针的错误,不太理想的做法是仅使用一些适当的值进行初始化。您可以跳转到错误所在的位置,单击变量并转到定义的位置,然后将其设置为适当的值。在大多数情况下,指针的值 NULL 是最安全的,因为如果它保持为 NULL 并且在没有被修改为正确值的情况下使用,您的应用程序应该会崩溃,让您知道存在问题。

通过初始化为NULL,您假设以前的程序员知道他们在做什么,并且编译器检测到的可能的流(s)将使变量保持不变为适当的值,因为逻辑永远不会发生。

如果发生未初始化的指针流,您会发现应用程序何时崩溃。不幸的是,追溯崩溃的根源可能很困难。

您可以在代码中使用assert 和其他测试来创建断点,以便在调试时创建断点或生成异常(如果是 C++),这可能比崩溃提供更多信息。因此,在生成错误的源代码行之前添加这样的测试,在使用指针之前检查测试中的NULL 可能会有所帮助。

或者,如果函数有一个状态码指示它是否工作,并且有任何错误以及返回错误状态的某种方式,那么最有效的方法是在可能未初始化的指针错误的指针处使用该错误报告如果完整性检查失败,则会生成。

但是,如果您能辨别出一个安全的默认值,您可能想改用它。辨别安全值需要查看源代码以确定安全默认值应该是什么。有时这样的安全值可以是初始化为零的适当类型变量的地址。

警告:如果要返回指针中的地址,请不要使用函数本地变量的地址。当函数返回时,该地址将不再有效,导致未定义行为。

警告 2: 如果预期指针中的地址是使用 malloc() 或 new 或类似的内存分配器分配的,那么您必须使用相同的机制,以便当某些代码决定使用free() 或delete 释放内存然后它会工作。

如果指针的值被本地化为函数本身,则此审查将需要阅读使用未初始化指针的函数的源代码。如果指针由函数返回,即函数导出给函数用户的值,那么您还需要查看使用函数的源代码以确定适当的默认值。

所以我建议你做的是,在你进行初始化的每个地方,你添加一个唯一的识别注释(类似于“Inhahe 修复未初始化的指针错误 06/10/2020”的行),以便你然后可以稍后进行搜索以找到这些,然后返回到有问题的代码中,并通过重构或更改代码来实际修复编译器错误,以消除可能的未初始化指针错误。

在您做任何事情之前,请先将源代码置于某种版本控制之下。

【讨论】:

  • 感谢您冗长且内容丰富的回复!也许这不是理想的做法,但我最终通过在 VS 2015 而不是 VS 2019 中编译 lib 来解决问题。我认为如果 VS 6 没有给出错误而 VS 2019 给出了,那么可能有一个中间版本不会出错,但足够现代,可以调用正确的库。我一直不愿意测试 VS 的每个版本,看看哪个版本不会出现错误,但后来我选择了 VS 2015 并且它工作正常,我会留在那里。不过,我会将此回复添加为书签以供将来参考。
  • @inhahe 听起来不错。我已经用一些关于 Visual Studio 2015/2017/2019 之间的 ABI 兼容性的附加链接更新了我的答案,这表明使用 Visual Studio 2015 编译的静态库应该与 Visual Studio 2019 编译的代码兼容。我的印象是,在 VS 2015 前后,微软才真正开始着手编译器的静态分析部分。我知道,从 VS 2005 到 VS 2013 的警告数量随着迁移到 VS 2015 而进一步增加。其中一部分来自添加到标准库中的新安全功能。
【解决方案2】:

虽然如果 X64 构建可以与旧的 32 位 VS6.0 构建链接会很棒,但我认为这将是一条艰难的道路。

我相信最好的希望是获取您拥有的 WinXP 代码并将其重新定位到 VS2019。在过去的几年里,我不得不这样做很多。
有一个 One Time Upgrade 路径,您只需在 VS6.0 工作区中阅读,它就会构建一组新的项目文件和 SLN 文件。

我对此的阅读使我相信 VS6->VSnewer 早在 VS2008 时间框架内就完成了,并且在 'C++' 和 MSBUILD 环境中存在一些“重大变化”,但你可以幸存下来并通过微小的更改获得可构建的代码。

我发现的一个问题是自定义构建步骤。任何带有路径的自定义构建步骤都需要在目录后面加上斜杠,并且任何带有引号的自定义构建步骤都可能被破坏,导致您的构建在 VS2013/VS2019 中挂起。 (我在这方面的工作是 VS2013)。 代码的主要问题可能是 for 循环 旧的 MS 编译器允许在 for 循环中声明的变量范围保持在预期范围之外。有一个编译器开关可以解决这个问题。

我记得 Platform Toolset V142 不支持 XP 系统,如果您需要针对 Win32 操作系统,那么您必须对这些二进制文件使用 V141_xp,否则源代码应该使用最新的平台工具集 V142 作为 x64 构建良好为现代窗户打造。我已成功将大量 VS6.0 用户程序迁移到 VS2013 和现在的 VS2019,但问题很少。

有一个 WIN32 #define 可以保留它,因为它是旧版并且不会破坏 x64 构建。

在 VS6.0 中,还有一个罕见的编译器错误,带有“字符串池”,其中生成的程序集将优化掉 2 个不同的字符串,就好像它们是相同的一样。字符串池在“执行并继续的程序数据库”中打开,这会在后台触发字符串池选项。所以我总是把它改成“程序数据库”,因为我从来没有看到过这个错误修复,并且怀疑它可能仍然在代码中。这个 bug 够讨厌也够难,以至于多年后我仍然很害羞。

Google 对 C 的重大更改。但现代编译器通常会强制执行 1998 年甚至没有定义的内容。我现在在编译时发现 许多错误,这些错误在 VS6.0 中被跳过/未注意到.

我会一次使用一个 CPP 模块,查看第一个错误然后往下走。那么你正在使用的这个漂亮的库就会有新的生命。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-23
    • 2023-03-21
    • 1970-01-01
    • 1970-01-01
    • 2018-08-11
    相关资源
    最近更新 更多