gpt4 book ai didi

c++ - 链接到MS Visual C上的protobuf 3时出错

转载 作者:塔克拉玛干 更新时间:2023-11-03 00:10:01 24 4
gpt4 key购买 nike

在Visual Studio上遇到 2013 ,但任何版本均可重现。

我从github克隆了 Protocol Buffer 库,在其上运行CMake-gui(我将所有内容保留为默认值,因此它是静态版本),仅构建了libprotobuf(其他项目由于某种原因而失败,cmd.exe错误,可能有事情要做测试,但libprotobuf可以正常运行)。

我的项目使用在mapbox vector 图块规范的github上找到的.proto文件生成的 header 。

链接时,我首先遇到此错误
Error 1 error C4996: 'std::_Copy_impl': Function call with parameters that may be unsafe - this call relies on the caller to check that the passed values are correct. To disable this warning, use -D_SCL_SECURE_NO_WARNINGS. See documentation on how to use Visual C++ 'Checked Iterators' s:\program files (x86)\microsoft visual studio 12.0\vc\include\xutility

我尝试在其他命令行参数中使用-D_SCL_SECURE_NO_WARNINGS禁用它,但是随后出现其他错误:
Error 1 error LNK2038: mismatch detected for 'RuntimeLibrary': value 'MTd_StaticDebug' doesn't match value 'MDd_DynamicDebug' in main.obj S:\eiogit3\misc-projs\mapload\mapload\libprotobufd.lib(common.obj)

最佳答案

这与项目和libprotobuf项目使用VStudio C(和C++)运行时库( VCRTLib UCRT -检查[SO]: How to circumvent Windows Universal CRT headers dependency on vcruntime.h (@CristiFati's answer))不匹配。让我详细说明一下:
假设有一些C(C++)代码。该代码的目的是要运行。可以实现:

  • 直接:在VC Application类型项目中包含该代码-这将生成一个.exe
  • 间接:将代码包含在VC库类型项目中-这将生成一个库,该库仅在从另一个.exe(调用该库)调用时才能运行。该库可以是:
  • 静态:所有C(C++)代码将被编译并存储在.lib文件中。在链接时在另一个项目中使用该库(无论是应用程序还是库)时,将需要该文件。请注意,.lib中所有需要的代码将被“复制”到另一个项目
  • 动态:现在将有2个文件:一个.dll文件,它将包含编译(和链接)的代码;一个.lib文件(1),它将包含指向该指针的“指针”(如果愿意) .dll文件中的代码。在另一个项目中使用该库时,在链接时也需要.lib文件,但是现在它不再包含代码,因此不会在其他库中复制(另一个库会更小),但是在运行时,其他库将需要.dll文件


  • 您可以检查 [SO]: LNK2005 Error in CLR Windows Form (@CristiFati's answer)以获取有关如何将C(C++)代码转换为可执行格式的详细信息。此外,Google充斥着有关静态库和动态库之间差异的文章,何时使用一种或另一种,可以在 [SO]: When to use dynamic vs. static libraries上找到一个示例。
    如您所料, CRT 或C RunTime库(包含使C代码能够运行的底层系统-一个示例是内存管理功能:malloc,free)也不异常(exception)-它等同于Nix的libc.a(静态或存档)与libc.so(动态或共享对象)的对比-但是在VStudio中,它要复杂一些:
  • 静态CRT驻留在libcmt.lib中
  • 动态CRT驻留在msvcrt.lib中,该文件“指向” msvcr ###。dll (2)(VStudio 2013的msvcr120.dll)

  • 注释:
  • 库名称(msvcr d .lib)末尾的“ d ”表示它是使用调试符号
  • 编译的
  • C++ 运行时库处于确切的情况;名称中有一个额外的 p :libc p mt.lib,msvc p rt.lib,msvc p 120.dll
  • 有关更多详细信息,请检查[MS.Docs]: CRT Library Features

  • 现在,UCRT部件不像任何其他lib(项目属性->链接器->输入->其他依赖项)一样包含在项目中,但是由于在编译时需要它们的性质(静态或动态),因此可以通过以下方式配置它们: [MS.Docs]: /MD, /MT, /LD (Use Run-Time Library) ,这里有4个可用选项:
  • 多线程(/MT )
  • 多线程调试(/MTd )
  • 多线程DLL(/MD )
  • 多线程调试DLL(/MDd )

  • 显然,包含“Debug”的是在构建时用于Debug配置的,而其他版本是在Release中。关键点是,具有 DLL 的版本正在使用 动态运行时版本,而其他版本则使用 静态版本。
    返回错误:链接器提示main.obj(项目的一部分)具有 MDd_DynamicDebug (与动态调试版本链接),而common.obj(libprotobuf项目的一部分)具有 MTd_StaticDebug (链接至静态调试版本),因此您可以在同一可执行文件(或.dll)中链接2个运行时-这是不可能的。
    为了对其进行修复,您应该确保libprotobuf和您的主项目的UCRT值相同。更改主项目设置以匹配libprotobuf的设置当然更简单,但是建议使用动态运行时版本(即使需要重新编译libprotobuf,它也会在涉及.dll的大型项目中变得困惑(嗯,如果更改该选项会产生使libprotobuf很难构建的错误,并且您的项目将保持这种简单状态,则可以使用静态UCRT)。
    注意:不要将libprotobuf的构建方式误认为UCRT类型(静态/动态)(此时为静态,但我敢肯定也可以将其构建为动态)。

    更新#0
    根据一些评论的要求,在上述注释中添加一些其他信息,这可能对其他用户很有用。
    关于库(包括libprotobuf)有2个方面,它们是 完全不相关的:
  • 库类型(构建方式):动态/静态
  • UCRT类型(使用UCRT的方式):再次,动态/静态

  • 因此,有4种完全有效的组合:
  • 使用动态UCRT的动态库
  • 使用静态UCRT的动态库
  • 使用动态UCRT的静态库
  • 使用静态UCRT的静态库

  • 对于libprotobuf,每个方面都由一个 bool cmake选项控制:
  • 库类型: protobuf_BUILD_SHARED_LIBS
  • UCRT类型: protobuf_MSVC_STATIC_RUNTIME

  • 可以通过以下任一方式设置2个标志:
  • cmake-gui
  • cmake cmdline(将它们作为参数传递-例如:-Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_MSVC_STATIC_RUNTIME=OFF)

  • 因此,以上4种组合是可能的(至少在v 3.5 中),但 #2。 默认情况下被禁用(指定 -Dprotobuf_BUILD_SHARED_LIBS=ON -Dprotobuf_MSVC_STATIC_RUNTIME=ON将构建一个.dll,该dll将链接到 动态 UCRT),以避免可能的运行时问题,并且启用它需要手动干预。
    有关构建指令(通过cmake)的更多详细信息,请检查: [GitHub]: protocolbuffers/protobuf - (master) protobuf/cmake/README.md

    脚注
  • #1 :仅当库导出符号时,才会创建.lib文件,否则该文件就没有意义(在链接时不需要任何操作,并且将创建.dll,但几乎无法使用)
  • #2 :对于较新的VStudio版本(以 v2015 开头), msvcr(t)部分已由 vcruntime 取代(或者至少是逻辑上的分割点,因为它是(检查开头的网址)
  • 关于c++ - 链接到MS Visual C上的protobuf 3时出错,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35116437/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com