使用gcc进行静态和动态链接

时间:2017-08-02 23:57:25

标签: c++ c

我最近一直在阅读关于静态和动态链接的内容,我理解了差异以及如何创建静态和动态库并将其链接到我的项目

但是,我想到了一个问题,我无法回答或找到它的答案,因为这是一个特定的问题...当我使用行编译我的代码时

if (length > 0 && activity.Text == "hero")
{
    var reply = ((Activity)context.Activity).CreateReply(string.Empty);
    reply.Attachments = new List<Attachment>();
    var heroCard = new HeroCard()
        {
            Text = "1)Hero Card Text\n\n2)next line!\n\n3)and another new line!"
        };
    reply.Attachments.Add(heroCard.ToAttachment());
    await context.PostAsync(reply);
}
else if (length > 0 && activity.Text == "hero html")
{
    var reply = ((Activity)context.Activity).CreateReply(string.Empty);
    reply.Attachments = new List<Attachment>();
    var heroCard = new HeroCard()
        {
            Text = "Hero Card Text <br/>next line!",
        };
    reply.Attachments.Add(heroCard.ToAttachment());
    await context.PostAsync(reply);
}

使用此命令进行编译

#include <stdio.h>
int main()
{
  printf("hello, world!\n");
}

这种类型的链接是什么? 所以stdio.h静态地或动态地链接到我的项目???

2 个答案:

答案 0 :(得分:1)

库主要用作共享资源,因此,几个不同的程序可以某种方式重用相同的预编译代码。一些库作为标准库提供,它们随操作系统和/或编译器包一起提供。一些图书馆附带其他第三方项目。

当您以示例的方式运行gcc时,您确实运行了一个编译器驱动程序,该驱动程序为您提供了一些与编译相关的函数,调用编译过程的不同部分并最终将您的应用程序与几个相关联标准库。根据您提供的限定符选择库的类型。默认情况下,它将尝试查找动态(共享)库,如果缺少将尝试静态。除非你告诉它只使用静态库(-static)。

当你链接到项目库时,你告诉gcc / g ++以某种方式使用哪些库(-lname)。以这种方式,它将与标准库一样,首先寻找'.so',然后寻找'.a'秒,除非使用-static。您也可以直接指定完整库名称的路径,实际告诉它使用哪个库。还有其他一些控制链接过程的限定符,请查看'g ++'和'ld'的人。

库必须包含真实的程序代码和数据。它链接到主可执行文件(和其他库)的方式是通过符号表,这些库是库的一部分。符号表包含全局函数和数据的条目。

共享库和静态库的结构略有不同。前一个实际上是一个预链接对象,类似于一个可执行映像,其中包含一些与符号和重定位相关的额外信息(这样的库可以加载到内存中的任何地址,但仍应正常工作)。静态库实际上是“.o”文件的存档,可以进行全面的链接。

创建库的常用步骤是将程序的多个部分编译为“.o”文件,这些文件又可以通过“ld”(或g ++)链接到共享库中,或者使用“ar”存档。 ”。之后,您可以使用它们以上述方式进行链接。

每个.cpp源文件创建一个目标文件(.o)。源文件包含代码,可以包含任意数量的头文件,在您的情况下为“stdio.h”(或cstdio)或其他任何内容。这些文件成为cpp预处理器保险的源的一部分。后者处理宏并展平所有#include层次结构,以便编译器只能看到一个转换为'.o'的文本流。通常,头文件不应包含可执行代码,而应包含声明和宏,但并不总是如此。但它并不重要,因为它们与主源文件焊接在一起。

希望这可以解释它。

答案 1 :(得分:0)

  

这种类型的链接是什么?所以stdio.h是静态的或   动态链接到我的项目???

stdio.h没有链接,它是一个头文件,包含代码/文本,没有编译对象。

正常的链接流程更喜欢&#39; .so&#39;图书馆在&#39; .a&#39;在同一目录中找到两者时归档。你的简单命令是链接到.so(如果它在正确的路径中)或.a(如果在没有.so等效的路径中找到它)。

要实现静态链接,您有多种选择,包括

1) copy the '.a' archive to a directory you create, then specify that 
directory (-L)

2) specify the path to the '.a' in the build command.   Boost example:

$(CC) $(CC_FLAGS)  $<  /usr/local/lib/libboost_chrono.a  -o $@  $(LIB_DIRs) $(LIB_NMs)

我使用了这两种技术,我发现第一种更容易。

请注意,存档代码可能引用其他存档中的符号。您可以命令链接器多次搜索库。

如果你让构建链接与.so,这不会将整个.so的副本拉入构建。相反,在程序启动后,.so(整个lib)在运行时加载到内存中(如果尚未存在)。对于大多数应用程序,这被认为是一个小型的&#39;程序调整其内存映射时启动性能受到影响(自动神奇地在幕后)请注意,应用程序本身可以控制何时加载.so,称为动态库。

相依:

// If your C++ 'Hello World' has no class ... why bother?
#include <iostream>

class Hello_t {
public:
   Hello_t()  { std::cout << "\n  Hello"  << std::flush; }
   ~Hello_t() { std::cout <<    "World!" << std::endl; }
   void operator() () { std::cout << " C++ "; }
};
int main(int, char**) { Hello_t()(); }