2

我已经将 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 没有'不支持多线程。

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

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

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

4

2 回答 2

2

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

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

有关版本之间的兼容性,Visual Studio 版本之间的库 ABI 兼容性,请参阅这篇文章, 另请参阅:

VS2017 和 VS2015 之间的二进制兼容性

Visual Studio C 库的 ABI 兼容性

微软发布的这篇关于 2019 年发布的 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缺少 a 的语句default:来捕获switch变量的事件不是指定的 case 值之一。这也可能是由于一个if语句是一系列else if没有最终else捕获任何其他可能条件的语句。或者也可能是由于break在指针变量初始化之前有一个语句的循环,或者它使用continue语句跳过了变量初始化的位置。

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

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

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

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

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

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

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

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

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

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

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

在你做任何事情之前,让源代码处于某种版本控制之下。

于 2020-06-11T00:42:47.933 回答
0

虽然如果 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 个不同的字符串,就好像它们是相同的一样。字符串池在“执行并继续的程序数据库”中打开,这会在后台触发字符串池选项。所以我总是把它改成“程序数据库”,因为我从来没有看到过这个问题的错误修复,并且怀疑它可能仍然在代码中。这个虫子够讨厌也够难,以至于多年后我仍然很害羞。

谷歌 C 中的重大变化。但通常现代编译器会强制执行 1998 年甚至没有定义的东西。我现在在编译时发现了许多在 VS6.0 中被跳过/未注意到的错误。

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

于 2021-08-18T23:20:54.163 回答