【问题标题】:Botan compile error VS2015Botan编译错误VS2015
【发布时间】:2015-08-04 07:08:14
【问题描述】:

我在这里遇到了一个奇怪的情况。我正在尝试将 Botan 加密库与 VS2015 一起使用(因为项目的其他一些部分使用了一些 VS2013 无法编译的繁重 C++11 代码)并且我得到了一个很长的编译错误(见下文)。

在尝试了各种方法后,我得出的结论是,即使编译后的 c++ 源文件中包含了其中一个 botan 头文件,编译器也会抛出以下错误。现在我在文件中有一行:

#include <botan/botan.h>

这是我得到的错误:

    C:\Program Files\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(876): error C2664: 'Botan::secure_allocator<_Newfirst>::secure_allocator(const Botan::secure_allocator<_Newfirst> &)': cannot convert
argument 1 from 'std::_Wrap_alloc<Botan::secure_allocator<Botan::byte>>' to 'const Botan::secure_allocator<_Newfirst> &'
        with
        [
            _Newfirst=std::_Container_proxy
        ]
C:\Program Files\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(876): note: Reason: cannot convert from 'std::_Wrap_alloc<Botan::secure_allocator<Botan::byte>>' to 'const Botan::secure_allocator<_Ne
wfirst>'
        with
        [
            _Newfirst=std::_Container_proxy
        ]
C:\Program Files\Microsoft Visual Studio 14.0\VC\INCLUDE\xmemory0(876): note: No user-defined-conversion operator available that can perform this conversion, or the operator cannot be called
C:\Program Files\Microsoft Visual Studio 14.0\VC\INCLUDE\vector(587): note: see reference to function template instantiation 'std::_Wrap_alloc<Botan::secure_allocator<_Newfirst>>::_Wrap_alloc<std::_Wr
ap_alloc<Botan::secure_allocator<Botan::byte>>>(_Other &) noexcept' being compiled
        with
        [
            _Newfirst=std::_Container_proxy,
            _Other=std::_Wrap_alloc<Botan::secure_allocator<Botan::byte>>
        ]
C:\Program Files\Microsoft Visual Studio 14.0\VC\INCLUDE\vector(587): note: see reference to function template instantiation 'std::_Wrap_alloc<Botan::secure_allocator<_Newfirst>>::_Wrap_alloc<std::_Wr
ap_alloc<Botan::secure_allocator<Botan::byte>>>(_Other &) noexcept' being compiled
        with
        [
            _Newfirst=std::_Container_proxy,
            _Other=std::_Wrap_alloc<Botan::secure_allocator<Botan::byte>>
        ]
C:\Program Files\Microsoft Visual Studio 14.0\VC\INCLUDE\vector(585): note: while compiling class template member function 'void std::_Vector_alloc<std::_Vec_base_types<_Ty,_Alloc>>::_Free_proxy(void)
'
        with
        [
            _Ty=Botan::byte,
            _Alloc=Botan::secure_allocator<Botan::byte>
        ]
C:\Program Files\Microsoft Visual Studio 14.0\VC\INCLUDE\vector(552): note: see reference to function template instantiation 'void std::_Vector_alloc<std::_Vec_base_types<_Ty,_Alloc>>::_Free_proxy(voi
d)' being compiled
        with
        [
            _Ty=Botan::byte,
            _Alloc=Botan::secure_allocator<Botan::byte>
        ]
C:\Program Files\Microsoft Visual Studio 14.0\VC\INCLUDE\vector(679): note: see reference to class template instantiation 'std::_Vector_alloc<std::_Vec_base_types<_Ty,_Alloc>>' being compiled
        with
        [
            _Ty=Botan::byte,
            _Alloc=Botan::secure_allocator<Botan::byte>
        ]
c:\Botan\include\botan-1.11\botan/rng.h(43): note: see reference to class template instantiation 'std::vector<Botan::byte,Botan::secure_allocator<Botan::byte>>' being compiled
NMAKE : fatal error U1077: 'C:\PROGRA~1\MICROS~3.0\VC\bin\cl.exe' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 14.0\VC\BIN\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files\Microsoft Visual Studio 14.0\VC\BIN\nmake.exe"' : return code '0x2'
Stop.

由于我能够编译和运行植物测试,我感觉我错过了一些东西,但我不知道是什么。有没有人有这方面的经验? (顺便说一句:相同的代码在 g++ 4.9 中编译得很好)

【问题讨论】:

  • std::_Wrap_alloc&lt;Botan::secure_allocator&lt;Botan::byte&gt;&gt;' to 'const Botan::secure_allocator&lt;_Newfirst&gt; &amp;': 可能传递的std::_Wrap_alloc 对象需要像operator * 这样的不恰当的操作才能得到一个可能可以转换为Botan::secure_allocator&lt;_Newfirst&gt;Botan::secure_allocator&lt;Botan::byte&gt; 对象?
  • 可能缺少包含(以允许转换Botan::secure_allocator)?
  • 我为答案添加了另一种可能的解决方法。
  • Botan 从未在 VS 2015 中进行过测试,因此它不太可能是库中的问题。感谢您提出这个问题。
  • 昨天发布的 Botan 1.11.20 修复了这个问题。再次感谢@bogdan!

标签: c++ c++11 visual-studio-2015 botan


【解决方案1】:

sources,好像Botan::secure_allocator没有提供form的模板构造函数

template<class U> secure_allocator(const secure_allocator<U>& other);

这是标准要求的。在当前工作草案N4527 中,相关位在 [17.6.3.5] 表 28 - 分配器要求中;第 9 段中的示例也很有用。

因此,我们不能责怪 VC 14 附带的标准库实现需要它才能编译。在我看来,错误在 Botan 一方。


快速解决方法是将这样的定义添加到Botan::secure_allocator

template<class U> secure_allocator(const secure_allocator<U>&) BOTAN_NOEXCEPT { }

由于这个分配器模板的实例没有任何非静态数据成员,一个空的主体应该没问题。但是,我对库不熟悉,我们在这里讨论的是密码学,所以,在使用它做任何严肃的事情之前,请与库作者确认更改。


另一种可能的解决方法:

我注意到调用混合类型构造函数的代码似乎只在启用迭代器调试时才启用,这在调试模式下默认发生。

您是否尝试过在发布模式下编译?如果我的观察正确,您将不会再收到此错误,因为用于迭代器调试的附加机制将被禁用。

要在调试模式下获得相同的行为,请将_ITERATOR_DEBUG_LEVEL 宏全局设置为0

调试迭代器可用于检测错误(只要性能损失不会影响您),因此我不会将此作为永久性修复,但如果您不这样做,它可能会用作临时解决方法'不想修改Botan头文件。

这也可以解释为什么您能够编译测试:也许它们是在发布模式下编译的,或者无论如何,使用禁用迭代器调试的设置组合?

【讨论】:

  • 我说得对吗,您建议添加显式复制构造函数?这可以解释错误,因为其他编译器会隐式执行此操作。
  • @SimonWarta 这不是复制构造函数。复制构造函数不能是模板特化,它们的第一个参数必须是对正在构造的类型的左值引用(我描述的那个可以采用secure_allocator 模板的任何其他特化)。据我所知,VC 14 在隐式生成特殊成员函数方面做得很好,所以这不是问题。不同的行为似乎是由 VC14 的 STL 中的迭代器调试引起的,但这仍然不能使分配器符合标准 - 需要模板构造函数。
  • 您能否将您的更改与背景信息一起添加为对 Botan 的拉取请求?在那里,我们可以从其他一些开发人员那里获得反馈。我不是模板方面的专家。
  • @SimonWarta 这样做我感到有点不安,因为我的机器上没有配置库,所以我实际上无法测试任何更改。所有这些只是我在看代码。确实,“构造函数无论如何都应该存在”的一般性声明仍然存在,但如果我们能够首先确认这两种解决方法,那就太好了,这样我们就知道什么受到了影响以及我们正在修复什么。
  • @j00hi 根据 Simon Warta 的comment above,版本 1.11.20 包含此修复程序。如果您需要使用旧版本并希望手动应用更改,则差异为 here