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

为什么运行库是编译器选项而不是链接器选项?

  •  13
  • mch  · 技术社区  · 17 年前

    我正试图使用visualstudio2005构建一个C/C++静态库。由于运行时库的选择是一个编译选项,我被迫构建我的库的四个变体,每个变体对应一个运行时库:

    • /MT-静态运行库
    • /MD-DLL运行库
    • /MTd-调试静态运行库
    • /MDd-调试DLL运行库

    这些是 编译程序 选项,而不是链接器选项。从Linux的背景来看,这似乎很奇怪。不同的运行库有不同的调用约定吗?为什么不能在链接时解析不同的运行时库,即当我链接使用我的静态库的应用程序时?

    6 回复  |  直到 17 年前
        1
  •  7
  •   bk1e    17 年前

    这些选项可能会添加在运行时库头文件中使用的定义(例如__DLL和__DEBUG)。一个常见的做法是在动态链接时将__declspec(dllimport)添加到函数声明中。

    编译器似乎也使用这些来帮助链接器链接到正确的库。这在 MSDN .

        2
  •  8
  •   zdan    17 年前

    C预处理器定义的一个副作用是 _DLL _DEBUG zdan提到:

    一些数据结构(如STL容器和迭代器)在调试运行时的大小可能不同,这可能是由于以下功能 _HAS_ITERATOR_DEBUGGING _SECURE_SCL 。您必须使用编译代码 structure definitions that are binary-compatible with the library you're linking to .

    如果混合和匹配针对不同运行时库编译的对象文件,您将收到以下链接器警告:

    warning LNK4098: defaultlib 'LIBCMT' conflicts with use of other libs
    
        3
  •  3
  •   Tim Ring    17 年前

    编译器需要知道您是生成单线程代码还是多线程代码。默认情况下,编译器生成线程安全代码(多线程)。如果你想要单线程代码,你必须告诉它。如果更改默认值,编译器将更改默认运行时库(您始终可以在链接器命令选项中覆盖此选项,只需确保您选择的库与目标文件具有相同的代码结构:单线程静态、多线程静态或多线程DLL)。请注意,没有单线程DLL选项(根据定义,运行时库DLL将被构建为线程安全的,因为它由多个应用程序共享)。

        4
  •  1
  •   Loki Astari    17 年前

    如果你忽略静态运行时,那么你会得到与Linux相同的选项。

    我知道静态运行时很有用,但我从来没有真正需要过它。此外,它还会导致处理内存分配/释放的潜在问题,因此我发现只使用DLL运行时更容易。

    发布/调试版本与Linux/Unix相同。
    尽管出于效率考虑,我也构建了单线程和多线程版本的库。

        5
  •  0
  •   Serafina Brocious    17 年前

    我认为这背后的原因是,SEH(结构化异常处理程序)代码的生成方式会因您链接到的运行时库而异。

        6
  •  0
  •   Lothar    15 年前

    为DLL和静态库生成了不同的机器代码。

    在Linux上,你也必须这样做,如果你想构建一个共享库,编译器标志叫做-fPIC。否则,在AMD64和SPARC(也许还有其他)上,它会崩溃。在i386架构上,链接器足够聪明,不会共享内存中的库,因此不会崩溃。