C ++:编译器和链接器功能 [英] C++: Compiler and Linker functionality

查看:109
本文介绍了C ++:编译器和链接器功能的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想要了解程序编译器的哪个部分以及链接器看起来是什么。所以我写了以下代码:

  #include< iostream& 
using namespace std;
#include< string>

class Test {
private:
int i;

public:
Test(int val){i = val;}
void DefinedCorrectFunction(int val);
void DefinedIncorrectFunction(int val);
void NonDefinedFunction(int val);

template< class paramType>
void FunctionTemplate(paramType val){i = val}
};

void Test :: DefinedCorrectFunction(int val)
{
i = val;
}

void Test :: DefinedIncorrectFunction(int val)
{
i = val
}

void main
{
Test testObject(1);
//testObject.NonDefinedFunction(2);
//testObject.FunctionTemplate<int> ;(2);

}

我有三个函数:




  • DefinedCorrectFunction - 这是正常声明和定义的正常函数。

  • DefinedIncorrectFunction - 此函数声明正确,但实现错误(缺少;)

  • NonDefinedFunction - 仅声明。无定义。

  • FunctionTemplate - 一个函数模板。



    现在如果我编译这个代码,在DefinedIncorrectFunction中缺少';'。

    假设我修复了这个问题,然后注释掉testObject.NonDefinedFunction(2)。现在我得到一个链接器错误。
    现在注释掉testObject.FunctionTemplate(2)。




对于函数模板,我明白他们没有被触摸由编译器除非它们在代码中被调用。因此,在我调用testObject.FunctionTemplate(2)之前,缺少的';'不会被编译器投诉。



对于testObject.NonDefinedFunction(2)抱怨,但链接器。为了我的理解,所有编译器关心是知道是一个NonDefinedFunction函数声明。它不关心实现。然后链接器抱怨,因为它找不到实现。到目前为止这么好。



我困惑的是当编译器抱怨DefinedIncorrectFunction。它没有寻找NonDefinedFunction的实现,但它通过DefinedIncorrectFunction。



所以我很少不清楚什么是编译器做什么和链接器做什么。我的理解是链接器链接组件与他们的调用。因此,当NonDefinedFunction被调用时,它寻找NonDefinedFunction的编译实现并投诉。但是编译器并不关心NonDefinedFunction的实现,而是对DefinedIncorrectFunction的实现。



我真的很感激,如果有人可以解释这个或提供一些参考。 >

谢谢。

解决方案

编译器的功能是编译您编写的代码并将其转换为目标文件。因此,如果你错过了一个; 或使用一个未定义的变量,编译器会抱怨,因为这些是语法错误。



如果编译没有任何障碍,则会生成对象文件。对象文件具有复杂的结构,但基本上包含五个


  1. 标题 - 有关文件的信息

  2. 对象代码 - 机器语言代码(在大多数情况下,此代码本身不能运行)

  3. 重定位信息 - 当实际执行发生时, / li>
  4. 符号表 - 代码引用的符号。它们可以在代码中定义,从其他模块导入或通过链接器定义

  5. 调试信息 - 由调试器使用



    1. 编译器编译代码并用遇到的每个符号填充符号表。符号是指变量和函数。 此问题的答案解释了符号表。


      这包含可执行代码和数据的集合,链接器可以将这些代码和数据处理成工作应用程序或共享库。对象文件具有称为符号表的数据结构,它将对象文件中的不同项目映射到链接器可以理解的名称。


      注意事项


      你从代码中调用一个函数,编译器不会把
      的例程的最终地址放在对象文件中。相反,它将一个
      占位符值添加到代码中,并添加一个注释,告诉链接器
      从所有处理的
      对象文件中查找各个符号表中的引用,并粘贴最终位置。


      生成的对象文件由链接器处理,将填充符号表中的空白,将一个模块链接到



      所以在你的具体情况下 -


      1. DefinedIncorrectFunction() - 编译器获取函数的定义,并开始编译它以生成目标代码并在符号表中插入适当的引用。

      2. NonDefinedFunction() - 编译器获取声明但没有定义,因此它向符号表添加一个条目,并将链接器标记为添加适当的值(因为链接器将处理一堆目标文件,这种定义可能出现在其他目标文件中)。在你的case你没有指定任何其他文件,所以链接器中止与 未定义的引用NonDefinedFunction 错误,因为它找不到引用


      3. 若要了解,还可以说您的代码结构如下:



        File- try.h

         #include< string& 
        #include< iostream>


        class Test {
        private:
        int i;

        public:
        Test(int val){i = val;}
        void DefinedCorrectFunction(int val);
        void DefinedIncorrectFunction(int val);
        void NonDefinedFunction(int val);

        template< class paramType>
        void FunctionTemplate(paramType val){i = val; }
        };

        档案try.cpp

          #includetry.h


        void Test :: DefinedCorrectFunction(int val)
        {
        i = val;
        }

        void Test :: DefinedIncorrectFunction(int val)
        {
        i = val;
        }

        int main()
        {

        测试testObject(1);
        testObject.NonDefinedFunction(2);
        //testObject.FunctionTemplate<int> ;(2);
        return 0;
        }

        让我们先复制和汇编代码, >

          $ g ++ -c try.cpp -o try.o 
        $

        这一步骤没有任何问题。所以你有在try.o中的目标代码。让我们尝试并链接它

          $ g ++ try.o 
        try.o:在main函数中:
        try.cpp :(。text + 0x52):未定义的引用`Test :: NonDefinedFunction(int)'
        collect2:ld返回1退出状态
        pre>

        您忘记定义Test :: NonDefinedFunction。让我们在单独的文件中定义它。



        File- try1.cpp

          #includetry.h

        void Test :: NonDefinedFunction(int val)
        {
        i = val;
        }

        让我们将其编译成对象代码

          $ g ++ -c try1.cpp -o try1.o 
        $

        再次成功。让我们尝试仅链接此文件

          $ g ++ try1.o 
        / usr / lib / gcc / x86_64- redhat-linux / 4.4.5 /../../../../ lib64 / crt1.o:在函数`_start':
        (.text + 0x20):未定义引用`main'
        collect2:ld退回1退出状态

        没有主人那么赢了't link !!



        现在,您有两个单独的目标代码,其中包含您需要的所有组件。只需传递BOTH的链接器,让它做剩下的

          $ g ++ try.o try1.o 
        $

        没有错误!这是因为链接器找到所有函数的定义(即使它分散在不同的目标文件中),并用适当的值填充对象代码中的空白。


        I want to understand exactly which part of a program compiler looks at and which the linker looks at. So I wrote the following code:

        #include <iostream>
        using namespace std;
        #include <string>
        
        class Test {
        private:
            int i;
        
        public:
            Test(int val) {i=val ;}
            void DefinedCorrectFunction(int val);
            void DefinedIncorrectFunction(int val);
            void NonDefinedFunction(int val);
        
            template <class paramType>
            void  FunctionTemplate (paramType val) { i = val }
        };
        
        void Test::DefinedCorrectFunction(int val)
        {
            i = val;
        }
        
        void Test::DefinedIncorrectFunction(int val)
        {
            i = val
        }
        
        void main()
        {
            Test testObject(1);
            //testObject.NonDefinedFunction(2);
            //testObject.FunctionTemplate<int>(2);
        
        }
        

        I have three functions:

        • DefinedCorrectFunction - This is a normal function declared and defined correctly.
        • DefinedIncorrectFunction - This function is declared correctly but the implementation is wrong (missing ;)
        • NonDefinedFunction - Only declaration. No definition.
        • FunctionTemplate - A function template.

          Now if I compile this code I get a compiler error for the missing ';'in DefinedIncorrectFunction.
          Suppose I fix this and then comment out testObject.NonDefinedFunction(2). Now I get a linker error. Now comment out testObject.FunctionTemplate(2). Now I get a compiler error for the missing ';'.

        For function templates I understand that they are not touched by the compiler unless they are invoked in the code. So the missing ';' is not complained by the compiler until I called testObject.FunctionTemplate(2).

        For the testObject.NonDefinedFunction(2), the compiler did not complain but the linker did. For my understanding, all compiler cared was to know that is a NonDefinedFunction function declared. It didn't care for the implementation. Then linker complained because it could not find the implementation. So far so good.

        Where I get confused is when compiler complained about DefinedIncorrectFunction. It didn't look for implementation of NonDefinedFunction but it went through the DefinedIncorrectFunction.

        So I'm little unclear as to what the compiler does exactly and what the linker does. My understanding is linker links components with their calls. So for when NonDefinedFunction is called it looked for the compiled implementation of NonDefinedFunction and complained. But compiler didn't care about the implementation of NonDefinedFunction but it did for DefinedIncorrectFunction.

        I'd really appreciate if someone can explain this or provide some reference.

        Thank you.

        解决方案

        The function of the compiler is to compile the code that you have written and convert it into object files. So if you have missed a ; or used an undefined variable, the compiler will complain because these are syntax errors.

        If the compilation proceeds without any hitch, the object files are produced. The object files have a complex structure but basically contain five things

        1. Headers - The information about the file
        2. Object Code - Code in machine language (This code cannot run by itself in most cases)
        3. Relocation Information - What portions of code will need to have addresses changed when the actual execution occurs
        4. Symbol Table - Symbols referenced by the code. They may be defined in this code, imported from other modules or defined by linker
        5. Debugging Info - Used by debuggers

        The compiler compiles the code and fills the symbol table with every symbol it encounters. Symbols refers to both variables and functions. The answer to This question explains the symbol table.

        This contains a collection of executable code and data that the linker can process into a working application or shared library. The object file has a data structure called a symbol table in it that maps the different items in the object file to names that the linker can understand.

        The point to note

        If you call a function from your code, the compiler doesn't put the final address of the routine in the object file. Instead, it puts a placeholder value into the code and adds a note that tells the linker to look up the reference in the various symbol tables from all the object files it's processing and stick the final location there.

        The generated object files are processed by the linker that will fill out the blanks in symbol tables, link one module to the other and finally give the executable code which can be loaded by the loader.

        So in your specific case -

        1. DefinedIncorrectFunction() - The compiler gets the definition of the function and begins compiling it to make the object code and insert appropriate reference into Symbol Table. Compilation fails due to syntax error, so Compiler aborts with an error.
        2. NonDefinedFunction() - The compiler gets the declaration but no definition so it adds an entry to symbol table and flags the linker to add appropriate values (Since linker will process a bunch of object files, it is possible this definitionis present in some other object file). In your case you do not specify any other file, so the linker aborts with an undefined reference to NonDefinedFunction error because it can't find the reference to the concerned symbol table entry.

        To understand it further lets say your code is structured as following

        File- try.h

        #include<string>
        #include<iostream>
        
        
        class Test {
        private:
            int i;
        
        public:
            Test(int val) {i=val ;}
            void DefinedCorrectFunction(int val);
            void DefinedIncorrectFunction(int val);
            void NonDefinedFunction(int val);
        
            template <class paramType>
            void  FunctionTemplate (paramType val) { i = val; }
        };
        

        File try.cpp

        #include "try.h"
        
        
        void Test::DefinedCorrectFunction(int val)
        {
            i = val;
        }
        
        void Test::DefinedIncorrectFunction(int val)
        {
            i = val;
        }
        
        int main()
        {
        
            Test testObject(1);
            testObject.NonDefinedFunction(2);
            //testObject.FunctionTemplate<int>(2);
            return 0;
        }
        

        Let us first only copile and assemble the code but not link it

        $g++ -c try.cpp -o try.o
        $
        

        This step proceeds without any problem. So you have the object code in try.o. Let's try and link it up

        $g++ try.o
        try.o: In function `main':
        try.cpp:(.text+0x52): undefined reference to `Test::NonDefinedFunction(int)'
        collect2: ld returned 1 exit status
        

        You forgot to define Test::NonDefinedFunction. Let's define it in a separate file.

        File- try1.cpp

        #include "try.h"
        
        void Test::NonDefinedFunction(int val)
        {
            i = val;
        }
        

        Let us compile it into object code

        $ g++ -c try1.cpp -o try1.o
        $
        

        Again it is successful. Let us try to link only this file

        $ g++ try1.o
        /usr/lib/gcc/x86_64-redhat-linux/4.4.5/../../../../lib64/crt1.o: In function `_start':
        (.text+0x20): undefined reference to `main'
        collect2: ld returned 1 exit status
        

        No main so won';t link!!

        Now you have two separate object codes that have all the components you need. Just pass BOTH of them to linker and let it do the rest

        $ g++ try.o try1.o
        $
        

        No error!! This is because the linker finds definitions of all the functions (even though it is scattered in different object files) and fills the blanks in object codes with appropriate values

        这篇关于C ++:编译器和链接器功能的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆