代码之家  ›  专栏  ›  技术社区  ›  MBZ

C++跨平台代码

  •  5
  • MBZ  · 技术社区  · 14 年前

    我们将在我们的小团队中启动一个新项目:

    • 它是一个库,将被我们的其他项目使用(在Linux和Windows中)。
    • 它在逻辑上不依赖于平台(它不使用任何系统调用或类似的东西)。
    • 它必须在各种平台上编译(至少包括Windows和Linux)。

    不幸的是,我们的开发人员中没有人在Windows以外的任何平台上编写过任何代码! 因此,我必须给他们一个 “这样的代码” “不是这样的代码” 列出,这样代码将保持跨平台。

    有什么指导吗?

    7 回复  |  直到 14 年前
        1
  •  10
  •   anon    14 年前

    提高可移植性的一种方法是在两个平台上使用相同的编译器gcc。如果您还使用相同的编译器版本,则可能避免大多数(如果不是所有的C++语言和标准库不兼容)。您还可以使用相同的构建工具,例如GNUmake,这意味着两个平台上的构建过程是相同的。

    至于平台不兼容-检查其代码是否不包含如下内容:

    #include <windows.h>
    #include <unistd.h>
    #include <sys/almost_anything.h>
    

    除非这是通过条件编译完成的。

        2
  •  7
  •   jcoder    14 年前

    确保在所有平台上都有自动化的构建过程,并编写单元测试和自动化功能测试。如果可能,运行自动的夜间构建和测试。在编写跨平台库时,这一点更为重要。

    我会做与其他答案相反的回答(不是我认为这是错误的,只是一种不同的方法),如果你可以选择你的平台,尽可能让它们不同。例如,在UNIX上创建一个32位MCVC和另一个64位GCC。如果您可以拥有自动化的测试和构建,那么这将很快显示可移植性问题。

    如果可能的话,让一些开发人员在一个平台上和另一个平台上工作,而不是在一个平台上完成代码,然后“移植”到另一个平台上。这样,当他们的同事过来抱怨他们弄坏了东西时,他们会很快学会不该做什么。

    技术上要注意的是

    • 不要假设int是32位
    • 不要假定字符有符号或无符号
    • 不要假定字符是ASCII格式的
    • 不要假设任何有关数据字节顺序或对齐的内容
    • 最小化指针算术。只有当你做出失败的假设时,你才会弄错。
    • 记住,文件名和目录名在不同的平台上的工作方式不同。如果您只需要移植到Windows和Unix,那么您可能就可以使用它了,但是一旦移植到两个平台,那么下一个端口可能是z系列或vms,在这些平台上,它们的工作方式会有很大的不同。
        3
  •  6
  •   Mike Seymour    14 年前

    最重要的是:让自动构建和测试一直在所有支持的平台上运行,以便直接获取大多数不可移植(或只是错误的)代码。

    语言本身、标准库和Boost应该可以移植到任何广泛使用的平台(当然是Linux/GCC和Windows/MSVC的现代版本)。怀疑以 .h ,并在决定使用其他库之前检查它们的可移植性。

    维护一个文档,记录您遇到的所有不兼容问题,所以希望您只犯一次错误。

        4
  •  5
  •   Collin Dauphinee    14 年前

    只需告诉他们不要使用WindowsAPI,这样他们就可以很好地使用了。

    如果在Visual Studio中开发,我还建议提高警告/错误级别,因为它会阻止您执行GCC(通常)不允许的某些操作,假设您使用GCC编译Linux。您还可以在项目设置中禁用Visual Studio扩展。

    显然,如果有人需要使用特定于平台的代码,那么他们应该使用定义来替换特定于平台的代码,这取决于该代码是在哪个平台上编译的。

        5
  •  2
  •   BatchyX    14 年前

    使用尽可能多的编译器进行编译,即使只在有限的平台上进行。我的头上,VC,GCC,英特尔,PGI。如果你能得到它们的一些旧版本,那也会有所帮助。所有的开发人员都不需要使用这些工具,而是每晚运行这些工具,并将结果提供给所有的开发人员。当问题出现时,修复问题要容易得多,而不是在您试图释放时尝试修复所有问题。

        6
  •  1
  •   Pontus Gagge    14 年前

    一些建议:

    • 使用 static_cast<> , dynamic_cast<> const_cast<> 而不是C型铸造。如果 reinterpret_cast<> 必须使用它,检查它,并用仔细的单元测试包围该代码。(这条规则的目的是禁止巧妙的旋转和依赖大小或对齐。)

    • 只使用现代标准C++库:没有MS特定库(BRRR!)MFC及其应用 CString .

    您可以添加一些建议 here 但是请注意,有些对相当现代的编译器来说过于悲观(例如,关于临时对象的建议16,以及18与库的STL部分直接冲突)。

        7
  •  0
  •   Community arnoo    7 年前

    从Windows开发人员在Linux上开发的经验来看,主要问题(如果您真的没有像您所说的那样使用依赖平台的代码)只是包含文件名中区分大小写的问题。除此之外,您将发现,默认情况下,gcc比msvc更严格,因此您可能需要加强一些内容,但它们通常非常简单。

    一件特别要注意的事是 std::map::erase does not return an iterator .