我正在尝试使用visual studio 2005构建一个C / C ++静态库。由于选择运行时库是一个编译选项,我不得不构建我的库的四个变体,一个用于运行时的每个变体图书馆:
这些是编译器选项,而不是链接器选项。来自Linux背景,这看起来很奇怪。不同的运行时库是否有不同的调用约定?为什么不能在链接时解析不同的运行时库,即当我链接使用我的静态库的应用程序时?
答案 0 :(得分:8)
这些选项可能会添加运行时库头文件中使用的定义(例如__DLL和__DEBUG)。一个常见的事情是在动态链接时将__declspec(dllimport)添加到函数声明中。
编译器似乎也使用这些来帮助链接器链接到正确的库。这在MSDN。
中有解释答案 1 :(得分:7)
zdan提到的C预处理器定义的一个副作用,如_DLL
和_DEBUG
:
某些数据结构(例如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
答案 2 :(得分:3)
编译器需要知道您是否生成单线程或多线程代码。默认情况下,编译器生成线程安全代码(多线程)。如果你想要单线程代码,你必须告诉它。如果你更改默认值,编译器会更改默认运行时库(你总是可以在链接器命令选项中覆盖它,只需确保你选择的库具有相同的代码结构作为您的目标文件:单线程静态,多线程静态或多线程DLL)。请注意,没有单线程DLL选项(根据定义,运行时库DLL将被构建为线程安全,因为它由多个应用程序共享)。
答案 3 :(得分:1)
如果忽略静态运行时,则会获得与Linux相同的选项。
我知道静态运行时可能很有用但我从来没有真正需要它。此外,它会导致处理内存分配/释放的潜在问题,因此我发现使用DLL运行时更容易。
发布/调试版本与Linux / Unix相同 虽然为了效率,我认为我还构建了一个单线程和多线程版本的库。
答案 4 :(得分:0)
我认为这背后的原因是SEH(结构化异常处理程序)代码将根据您链接的运行时库的不同而生成。
答案 5 :(得分:0)
为DLL和静态库生成了不同的机器代码。
在Linux上你必须这样做,如果你想建立一个共享库,编译器标志被称为-fPIC。否则在AMD64和SPARC(以及其他人)上会崩溃。在i386架构上,链接器非常聪明,不会在内存中共享库,因此不会崩溃。