c++ /小牛最佳实践

本指南主要地址如何适应C / c++代码Bioconductor包在Mac OS X 10.9中(小牛)。如果你的包不使用C或c++代码,你可以假设这个文档不相关。

表的内容

本文写的是从头读到尾,除了最后一节。

你可能会跳过的教训了部分,检查你的问题是否已经被探索。

取向

注意:为简单起见,本指南使用GCC (GNU Compiler Collection)和“叮当声”是指每个各自收集的工具(包括c++编译器),而不是简单的“C编译器GCC”或“叮当声C编译器”。“小牛环境”指的是叮当声和Xcode版本默认为小牛。

与小牛的释放R的构建,凹口和Bioconductor采用了苹果的首选工具链为小牛平台构建方案。Bioconductor包都是建立在小牛平台使用OS X默认的组合铿锵声Xcode

小牛的引入环境暴露了很多问题与构建包,其中大部分是由于C / c++代码过于依赖海湾合作委员会的行事方式。大多数问题揭示了过渡到小牛队是由c++编码实践公认的问题,和解决的坚持最佳实践

下面是一些常见的来源问题,摆出一副如何小牛环境与GCC:

不同的对小牛发展环境是什么?

最大的变化是引入的叮当声libc + +11 c++标准库的实现和图书馆头与Xcode有关。铿锵声是获得市场份额的原因有几个,得益于这一事实叮当声仅用于基于c的语言的编译器。支持者的叮当声,叮当声:

为指导编译器标志使用而发展中,看到的相关部门的计划指南页面

未指明的行为的差异,内存寻址的政策

在转换过程中遇到的一些错误似乎归因于依赖不可移植的未指定的行为。看到这个指南的部分未指明的行为为更多的信息。

例如,C / c++内存寻址的许多方面是依赖于实现的,这意味着预期行为不是C / c++标准规定(“不明”),因此由编译器决定。

关于内存的最重要的区别是叮当声似乎更加严格禁止入内的内存寻址。

如何找到错误

GCC首选的调试器广东发展银行,但很多人喜欢lldb小牛的调试环境。支持在其他平台上lldb是有限的。

因为一个包相关的bug数量内存寻址或布局错误,依靠调试器本身可能不足以跟踪内存错误。Valgrind是检测内存错误的工具。

看到Bioconductor指南调试C / c++代码使用调试器和Valgrind的例子。

如果我不能访问一个小牛机器吗?

没有使用小牛机替代解决方案,在小牛失败。许多的错误只可再生的叮当声的组合,Xcode, OS X 10.9。

但是有几个选项的采购小牛机:

  1. 作为一个勘探测量,安装最新版本的GCC和编译您的软件包化c++ 11化gnu c++ 11编译器参数(见计划的指导方针信息开发编译器标志);的版本4.8.1,GCC实现的所有主要特征2011 ISO c++标准。诊断错误和警告也大大提高了与最近的GCC版本。使用一个c++ 11实现可能会显示警告或错误,指向同一个问题遇到了小牛。

  2. 安装铿锵声;这是有限的价值,因为许多错误是小牛独有的环境。

  3. 使用Valgrind内存寻址问题;因为很多错误在小牛平台相关内存寻址问题,许多错误应该同样使用Valgrind Linux上发现的。

  4. 如果你不能使用的结合诊断出你的问题构建系统的输出和Valgrind,随时联系bioc-devel邮件列表

c++ 11

虽然默认的版本的叮当声小牛包括支持c++ 11所有功能,Bioconductor支持c++ 11依赖平台和最古老的工具链。因为当前的雪豹(Mac OS x10.6.8)工具链不支持任何c++ 11特性,Bioconductor包通常不应该使用c++ 11特性。最终,当小牛更广泛的采用,对雪豹的支持将会下降。

c++ 11完全向后兼容旧标准。

可以告诉叮当声使用旧版本的标准库(默认libc + +),但依靠操作系统特定于版本的编译设置并不是一个可行的长期解决方案。这种方法大大增加了包的维护负担作者和限制Bioconductor团队提供支持的能力。

代码应该是适应避免落后——或者forward-incompatible构造。看到forward-incompatibility问题部分例子。

特定于小牛队的环境问题

C链接

c++使用外来的“C”给声明C链接,因此使声明访问C代码。一些R头的时候# included在c++中应该包括c++系统头文件C链接。根据相关的编写R扩展手册部分,R头文件应该被包括在外来的“C”块。

一个坏链接的典型症状是在包加载时间(不是编译或链接时)说一个错误无法找到一个特定的符号。

解决方案:所有R头应该是# included外来的“C”块。

正确的例子# includeR的标题:

# include < R。h >外来的“C”{空白foo ();/ /函数“foo”和其他代码块C链接……}外来的“C”空白栏();/ /函数“酒吧”C链接

OpenMP

在撰写本文时小牛环境不支持OpenMP未知,如果苹果发布的工具。

代码不应该依赖于可用性的OpenMP。独立的担忧OpenMP的支持,应该从一开始就写代码很好地降低在单线程环境中。

看到编写R扩展手册部分在R包信息OpenMP代码,检测的支持。

解决方案:使用预处理器if - else指令代码优雅地降解如果OpenMP支持不可用:

# ifdef SUPPORT_OPENMP / /多线程OpenMP其他版本的代码# # endif / /单线程版本的代码

看到ShortRead方案围绕支持OpenMP良好实践的一个例子。

c++的最佳实践

这些c++实践适用于大多数c++项目,但发现了Bioconductor社区特别有助于避免问题在小牛的环境中。

使用Rcpp

Rcpp凹口包允许c++的无缝集成R,是跨平台的。包提供的许多相同的好处RC接口让c++作为一种语言,而消除许多编程的陷阱R接口。

包是有据可查的,有一个广泛的工作示例库对于许多任务:Rcpp画廊

避免名称解析错误

名称解析错误发生在编译器遇到一个标识符(例如,变量或函数名),模棱两可的(也就是说,有一个两个或两个以上的标识符之间的“碰撞”),或名称查询规则不正确导致编译器解决一个名称。铿锵声更严格的标识符。

名称解析错误的典型症状是编译器抱怨一个函数的参数类型或数量有不同于预期,以及编译器指向一个c++标准库的头文件。

有两个主要问题名称解析写作时R包:

重新映射标识符从R的头

为了方便起见,R别名共同标识符R头。例如,Rf_length(饱和度指数)就变成了长度(饱和度指数)。虽然这可能是方便C小牛环境中,组织的头似乎比GCC导致更多的冲突。看到的相关部分编写R扩展手册

解决方案:防止重新映射R为c++代码标识符定义R_NO_REMAP象征。可以在包级别-DR_NO_REMAP预处理器国旗,或去审校#定义R_NO_REMAP。使用完全限定版本的R标识符,通常通过将Rf_

例子摘自防止重新映射的头文件:

文件CxxCode。h - - - - - - - - - - - - - - - - - -的ifndef CXX_CODE_H # define CXX_CODE_H # ifdef __cplusplus #定义R_NO_REMAP # endif……空白foo(饱和度指数s){如果(Rf_length (s) > 1) / /完全限定:“Rf_length”……}# endif

请注意Rf_length只是一个例子的吗R标识符可能冲突c++标准库头文件的名称。

名称空间的卫生

介绍了名称空间在c++中限制名称冲突的发病率。然而,许多作者新c++使用using引用(特别是“使用名称空间性病不必要的指令),从而引入名称空间是为了解决问题。

指出的cppreference笔记部分的使用使用名称空间性病指令介绍整个性病命名空间名称解析。可能性高在所有标准库的头文件有冲突的一个标识符标识符在你的包。

解决方法:避免“使用名称空间性病的指令完全如果可能的话,特别是在头文件中。更喜欢使用- - - - - -声明在using引用或简单地使用完全限定的标准库的版本标识符。新的c++作者高估了包括范围解析操作符(即“std::”)影响可读性。

介绍性病名称空间标识符的例子:

# include <地图> # include <效用> / /假设我们想访问std::地图和std:: make_pair标识符

许多新的c++作者将使用一个使用指示介绍他们所需要的标识符。避免如果可能的话:

使用名称空间性病;/ /介绍整个性病名称空间解决

另一个选择是通过声明(例如,“使用std::地图;的标识符,允许手工采摘介绍(而不是整个std名称空间);在这里,我们只是希望std::地图std:: make_pair。即使我们想要的标识符列表很长我们只需要为每一个单个using声明:

使用std::地图;/ /“地图”和“make_pair”在声明范围使用std:: make_pair;

通过声明也可以block-scoped。这是在全球范围内优先于通过声明,因为它可以防止不必要的介绍的名字在全球范围,良好的命名空间卫生的宗旨:

空白foo(){使用std::地图;使用std:: make_pair;map < int, int > m;m。插入(make_pair (5、7));…}

一个完美的替代方法是简单的标准库标识符之前的std::”,大多数c++程序员习惯于阅读:

空白foo () {std::地图< int, int > m;m。插入(std:: make_pair (5、7));}

避免未定义行为和不可移植的未指定的行为

有两个主要类别的行为不是规定的C或c++标准:

问题的一个典型症状未定义或不特定的行为是段错误,只有出现在小牛的环境。原因可能是之前发现的问题不是GCC默默地允许代码执行程序,而不是崩溃。

解决方案:防守,以避免有问题的结构和代码使用调试器找到的代码会导致错误。

从外部来源问题的代码

包需要使用一些代码没有写直接由贡献者(年代)。最常见的情况是包括一个库的源代码由一个第三方写的。一些还包使用代码产生的代码生成工具,例如,痛饮。首先,看到有关包指南部分指导代码从外部来源。

看到经验教训部分的指南建议对具体代码的来源。

生成的代码

有些包使用第三方工具生成的代码,即。,代码写的机器。痛饮是一个常见的例子。

写的代码的问题是代码是机器由机器。每一个代码文件的顶部由痛饮,例如,国家代码不是读或手工编辑。

因为许多代码生成工具让小牛环境,假设是无效的代码需要人类注意修复错误;但是因为machine-written冷漠本质的代码很难隔离错误。

解决方案:重新生成代码问题如果可能的话,否则手工修复。用手固定是强烈的打击

第三方代码

一些包包括第三方库没有书面compiler-independent的方式,所以不要在小牛环境建立的开箱即用。

在近似的偏好顺序解决方案:

  1. 检查现有的凹口或Bioconductor包提供相同的功能,而满足性能需求的用例。消除第三方代码从你包大大减少了维护的负担。

  2. 检查库已更新。一些图书馆与一个活跃的用户社区进行更新,添加更多的编译器/环境的支持。

  3. 检查维护人员都知道图书馆不为小牛的环境中工作,并找出如果支持即将到来。通常很容易直接接触的作者库维护的个人或小组。

  4. 使用一个积极维护备用库,提供了相同的功能。有时如果图书馆不再维护,因为图书馆已经抛弃了另一个项目,它提供了相同的功能。

  5. 更新库代码包含在你的包。强烈的打击。为保持代码维护人员承担责任与主流开源项目最新的。如果实施,记录的描述需要改变,所以当更新代码库的变化可以很容易地复制。

从具体问题的经验教训

这部分作为一个组织松散的存储库获得的知识对具体问题及其解决方案。它不会是全面的。项目将随着知识库的发展。Bioconductor渴望的建议;请写bioc-devel邮件列表如果你有任何!

如果你不知道从哪里开始诊断您的破包有必要掠过这一节。

相关的地方,这个问题被标记为在编译时或运行时被发现的。

在适用情况下,现场演示代码提供的链接。

c++ Forward-incompatibility问题11

c++ 11并非完全向后兼容的。特别是,API标准库的一些地区也发生了微妙的变化,也许在微妙的方式。大多数问题需要最小的调整来解决。

容器的迭代器const-ness

类型:编译时

许多操作标准库容器现在需要迭代器常量。两个例子是做好了准备插入擦除用迭代器参数的方法。

标准库容器迭代

类型:运行时

一般来说,使用特殊的结束之后迭代器的价值除了平等检查(例如,= =! =)导致未定义行为。特别是,在小牛环境:

预排的例子的递增结束之后,请参阅diagnose-a-crash例子在调试C / c++页面。

外部代码来源

外部代码来源的常见例子痛饮,提高和很多文件格式库。编写的代码从外部来源有时non-compiler-independent方式。检查文档,看看小牛队环境支持。

提高

提高是一个免费的来源,同行评议的c++库,提高语言。增加许多地方是“只包括头文件”,这意味着他们不需要单独编译和标题只需要出现在搜索路径为了让客户机代码使用它们。

许多Boost库是独立于平台的,但不是全部。一些Boost库添加小牛环境支持的过程中,作者或图书馆已经宣布支持将小牛的环境被添加。

在近似的偏好顺序解决方案:

  1. 使用黑洞包在凹口,如果可能的话。BH包提供了一些提高只包括头文件的库。使用BH包意味着使用Boost的维护成本几乎没有什么在你的包。

  2. 更新Boost库你包括你的包。Boost库有时包含错误,或者是后来更新添加对其他平台的支持。Bioconductor包维护人员的责任是保持所有的代码在包更新。

  3. 联系的作者特定的Boost库。如果你不能找到一个公告关于支持小牛环境中,它可能是值得作者询问联系图书馆。

痛饮

痛饮生成代码之间的接口代码用C / c++编写和其他语言。在撰写本文时,叮当声大喝支持是有限的,叮当声,痛饮特别问题的libc的c++版本(c++标准库。有些问题是有限的问题可以通过调整解决函数签名。其他问题是深深植根于痛饮产生代码的方式。

在撰写本文时,这个线程SWIG-devel邮件列表似乎最深入的讨论与小牛痛饮。

在近似的偏好顺序解决方案:

  1. 消除痛饮代码,如果可能的话。这可能会做最减少维护的负担。

  2. 重新生成大口大口的最新版本的代码。在撰写本文时痛饮最近被更新以包含部分支持c++ 11,这可能会缓解问题的叮当声libc + +。看到痛饮对c++ 11支持文档。新版本有可能不会产生问题的代码。注意代码必须为所有支持的编译器是有效的。

  3. 故障诊断和修复错误。强烈的打击。如果实施,记录的描述需要变化,所以如果代码是再生的变化可以很容易地复制。

    痛饮文档找到关于故障诊断指导。(例如,痛饮- e开关预处理程序运行后输出结果。)也许先删除所有痛饮功能,逐步添加特性。在网上找到的信息关于如何修复错误的包。

f2c

f2c是一个工具,将Fortran77代码转换为C / c++代码。使所需的维护负担f2c实质性的跨平台的代码。因为一个fortran编译器(或模拟器)需要安装R,f2c通常是不必要的。几包使用本机fortran代码没有问题。

解决方案:如果可能的话,删除f2c的必要性。唯一的办法是手腕makefile,每种受支持的平台或多或少地有针对性的makefile。请写bioc-devel邮件列表如果你有麻烦。