将C ++代码从GCC移植到MSVC的良好做法?

时间:2018-12-10 14:52:04

标签: c++ visual-c++ portability

我是一名学生,目前正在上编译器构造课程。我使用GCC和CMake在Ubuntu上用C ++开发了我的编译器。虽然在我的开发机器上一切正常,但在学校测试中针对MSVC或Visual Studio 2017编译时,代码却可怕地崩溃了。当我跟踪MSVC引发的错误消息时,我注意到导致这些失败的原因有几个:

  • GCC的标头比MSVC提供的内容更多。
  • 我无法解释的其他一些奇怪的错误(对不起,但我可以找到一个更好的词)。

要进行讨论,请参见以下示例, 适用于GCC,但在MSVC上无法使用。

#include <iostream>

int main() {
  std::string S;
  std::getline(std::cin, S);
}

MSVC要求#include <string>正常工作。

#include <unordered_map>

int main() {
  std::min(1, 2);
}

MSVC要求#include <algorithm>正常工作。

这些问题一旦爆发就不难解决:我可以#include所需的标头。但是,让它们爆发的价格太贵。它夺走了我的分数并伤害了我。

我没有兴趣讨论哪种编译器更符合标准。我只是想先解决任何可移植性问题,然后再抓住我。但是我对这些编译器之间的所有棘手差异并不了解。这就是为什么我需要工具来解决这些问题。我想更新工具链以编写更多可移植的代码。

编辑:除了工具之外,我还将谦虚地学习编写可移植代码的所有代码纪律,良好实践和已知问题。

编辑:抱歉!我并不是要使第二个示例错误(只是删除)。我只是无法访问MSVC来重现问题。

编辑以澄清问题不是该帖子的目的:

  1. 将代码从GCC移植到MSVC时如何解决某些问题。
  2. 如何编写通用编译的符合标准的C ++代码。

实际上,这篇文章要求人们采取实际行动,将代码从GCC移植到MSVC或更好,以便从一开始就编写没有可移植性问题的代码。这篇文章中的示例用于使讨论更具体或显示实际困难,但并不全面。我不认为这个问题有一个单一的真理,但我想尝试一些好的问题。

1 个答案:

答案 0 :(得分:1)

针对多个编译器进行编译

关于可移植性,有两种方法。一种迷人的,理想的,但不切实际的方法:您希望编写绝对可移植的代码:即,可以在当前和将来的任何编译器上工作,无论是实际的还是虚构的。您可能会想说:嘿,这只是标准的C ++代码。不幸的是,编译器是软件,并且像任何复杂的软件一样,它们都有错误。此外,该标准还包含 bug (缺陷报告可追溯应用)。您编写的代码越复杂,遇到这些错误的机会就越多。

另一种方法是实用的方法。并非针对100%可移植的代码,而是针对在一组体系结构上的一组编译器版本上实现可移植性。例如,您可以针对您的代码在x64 linux和Windows(最新版本gcc clangmsvc或从x向上的版本)上运行而忽略其他所有内容。 (该死)。为此,实际上只有一种方法:在所有这些平台上测试代码。为此,您至少需要为代码创建单元测试,然后在所有体系结构和编译器上编译并运行这些测试。您可以手动执行此操作,也可以自动执行该过程(例如CI)。

在多个编译器上运行代码,您将发现您需要修改代码以使其更符合标准,或者为不同的编译器和版本编写不同的代码,以避开错误或限制。 SO充满了在某些主要编译器(版本)或其他编译器上不起作用的兼容代码。

使用适当的开关进行编译

编译器具有自定义扩展名(默认情况下已启用某些扩展名)。您应该禁用它们。它是特定于编译器的。例如,对于gccclang,您需要-pedantic。我不知道msvc。但即使是这些are not enough

  

某些用户尝试使用-Wpedantic检查程序是否符合严格的ISO C   一致性。他们很快发现它并不能完全满足他们的要求:   它找到了一些非ISO的做法,但不是全部-仅针对那些ISO做法   C需要诊断,而其他一些则需要诊断   

使用补充编译器的工具

使用static analyzer工具。这些工具会分析您的代码,并发现一些错误,非法或未定义行为的代码。

也请看一下lang消毒剂。

别忘了标准

您说您对讨论哪个更符合标准不感兴趣,但是至少应该对符合标准的代码感兴趣。例如,在您的第一个示例中,即使它碰巧适用于您的gcc版本,该代码也是非法的,因为此处的标准要求包含<string><algorithm>

当您遇到在不同的编译器上以不同方式工作的代码时,您绝对应该研究并查看符合标准的内容。