我认为您误读了您提供的链接中的文档。特别是,您误解了它的目的——该部分标题为“目标”,描述了一些 C++ 调试库的假设设计以及这些设计的后果,以便解释实际的设计选择。在您引用的那些行之后的文本描述了会导致混乱的
假设实现,该实现具有发布模式和调试模式字符串的不同设计。它继续说:
“因此,我们无法为 std::basic_string 类模板轻松提供安全迭代器,因为它存在于整个 C++ 标准库中。”
(或者,重新表述一下,提供一个特殊的“调试”版本的字符串迭代器是不可能的。)
“...”
“使用 libstdc++ 调试模式的设计,我们无法有效地隐藏调试和发布模式字符串之间的差异。未能隐藏这些差异可能会导致不可预测的行为,因此我们选择仅执行不需要 ABI 更改的 basic_string 更改。对用户的影响预计将是最小的,因为有简单的替代方案(例如 __gnu_debug::basic_string),而从能够混合调试和发布编译的翻译单元获得的可用性好处是巨大的。”
换句话说,GCC的libstdc++中的调试和发布模式设计已经拒绝了这种假设的实现,具体来说是为了允许跨模式链接,而你所担心的避免交叉链接的问题不应该出现。
因此,您应该没有问题地编译您的库一次,无需使用
-D_GLIBCXX_DEBUG
(或如果出于某种原因您更喜欢它,则使用它),然后将其与应用程序的任何模式链接。如果出现问题,则是由于某个错误。[但请参见下面的编辑!这仅适用于
std::string
,而不适用于其他容器!]
编辑: 在被接受之后,我回答了
std::vector<std::string> crash的后续问题,并意识到这个答案的结论是错误的。 GCC的libstdc++对字符串做了巧妙的处理,以支持“每次使用重新编译”(在其中给定容器对象的所有用途必须使用相同的标志进行编译,但程序中使用相同容器类的用途不需要使用相同的标志进行编译),但这并不等同于完全的“每单元编译”,这将提供您所需的交叉链接能力。特别地,文档对于该交叉链接能力表示:
我们认为,如果我们打算提供安全迭代器,保持程序语义不变,并且在发布模式下不会性能回归,那么实际上不可能达到这种程度的重新编译....
因此,如果您在库接口中传递容器,则
必须 需要两个单独的库。老实说,对于这种情况,我发现最简单的解决方案就是将这两个库安装到不同的目录中(每个变体一个目录--您会希望它们都与主库目录分开)。或者,您可以重命名调试库文件,然后手动安装它。
另一个建议是--您可能不经常在调试模式下运行此程序。将调试版本仅编译并静态链接到应用程序中可能值得考虑,这样您就不必担心安装多个动态库并在运行时保持它们正确。