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

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

问题描述

我想准确了解程序编译器查看的部分以及链接器查看的部分.于是我写了如下代码:

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);

}

我有三个功能:

  • DefinedCorrectFunction - 这是一个正确声明和定义的普通函数.

  • DefinedCorrectFunction - This is a normal function declared and defined correctly.

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

DefinedIncorrectFunction - This function is declared correctly but the implementation is wrong (missing ;)

NonDefinedFunction - 仅声明.没有定义.

NonDefinedFunction - Only declaration. No definition.

FunctionTemplate - 一个函数模板.

FunctionTemplate - A function template.

现在,如果我编译此代码,我会得到一个缺少 ';'in DefinedIncorrectFunction 的编译器错误.
假设我修复了这个问题,然后注释掉 testObject.NonDefinedFunction(2).现在我得到一个链接器错误.现在注释掉 testObject.FunctionTemplate(2).现在我得到一个缺少';'的编译器错误.

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 ';'.

对于函数模板,我知道除非在代码中调用它们,否则编译器不会触及它们.所以缺少';'在我调用 testObject.FunctionTemplate(2) 之前编译器不会抱怨.

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).

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

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.

当编译器抱怨 DefinedIncorrectFunction 时,我感到困惑.它没有寻找 NonDefinedFunction 的实现,而是通过了 DefinedIncorrectFunction.

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

所以我不太清楚编译器到底做了什么以及链接器做了什么.我的理解是链接器将组件与其调用联系起来.因此,当调用 NonDefinedFunction 时,它会查找 NonDefinedFunction 的编译实现并抱怨.但是编译器并不关心 NonDefinedFunction 的实现,但它关心的是 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.

谢谢.

推荐答案

编译器的作用是编译你写的代码,然后转换成目标文件.所以如果你错过了一个 ; 或者使用了一个未定义的变量,编译器会报错,因为这些是语法错误.

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 - 关于文件的信息
  2. 目标代码 - 机器语言代码(此代码在大多数情况下无法自行运行)
  3. 重定位信息 - 当实际执行发生时,哪些代码部分需要更改地址
  4. 符号表 - 代码引用的符号.它们可以在 this 代码中定义、从其他模块导入或由链接器定义
  5. 调试信息 - 由调试器使用
  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.

注意事项

如果您从代码中调用函数,编译器不会将目标文件中例程的最终地址.相反,它放置了一个占位符值到代码中并添加一个告诉链接器的注释从所有的各种符号表中查找引用它正在处理的目标文件并将最终位置固定在那里.

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() - 编译器获取函数的定义并开始编译它以生成目标代码并将适当的引用插入符号表.由于语法错误,编译失败,因此编译器因错误而中止.
  2. NonDefinedFunction() - 编译器获得声明但没有定义,因此它向符号表添加一个条目并标记链接器以添加适当的值(由于链接器将处理一堆目标文件,因此该定义可能存在于某些其他目标文件).在您的情况下,您没有指定任何其他文件,因此链接器会以 undefined reference to NonDefinedFunction 错误中止,因为它找不到对相关符号表条目的引用.

为了进一步理解它,假设您的代码结构如下

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

文件-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

#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
$

这一步没有任何问题.所以你在 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

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

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

文件-try1.cpp

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天全站免登陆