标准C ++库链接 [英] Standard c++ library linking

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

问题描述

我试图了解标准库何时链接到我自己的二进制文件.我写了以下内容:

I'm trying to understand when does standard library linking to my own binary. I've written the following:

#include <stdio.h>

double atof(const char*);

int main(){
    const char * v="22";
    printf("Cast result is %f", atof(v));
}

使用g++ -c main.cpp编译成功,但是当我链接刚创建的目标文件时出现错误.错误描述是:

It's compiling successful with g++ -c main.cpp, but when I'm linking just created object file I've an error. Error descriptio is:

/tmp/ccWOPOS0.o: In function `main':
main.cpp:(.text+0x19): undefined reference to `atof(char const*)'
collect2: error: ld returned 1 exit status

但是我不明白为什么会导致此错误?我认为标准的c ++库通过ld链接程序自动链接到我的二进制文件.包含头文件和只声明一个我需要显式使用的函数之间有什么区别.

But I don't understand why this error is caused? I think that the standard c++ library automatically linked to my binary by the ld linker. What is the difference between the including header files and just declaring a functions which I need to use explicitly .

推荐答案

作为C ++中的一般规则,手动声明诸如atof()之类的库函数是一个坏主意.

As a general rule in C++, it is a bad idea to manually declare library functions such as atof().

它在旧的C程序中曾经很常见,但是C没有函数重载,因此对于几乎"正确的声明更为宽容. (有些旧的编译器是,我不能真正代表最新的编译器).这就是为什么我们将C描述为弱类型"语言,而将C ++描述为更强类型"语言.

It used to be common in old C programs, but C doesn't have function overloading so it is more forgiving about "almost" correct declarations. (Well some of the old compilers were, I can't really speak for the newest ones). That is why we describe C as a "weakly typed" language, while C++ is a more "strongly typed" language.

另一个麻烦是,编译器执行名称修改":它们传递给链接器的名称是源名称的修改版本. C编译器可能执行与C ++编译器完全不同的名称处理. atof()的标准lib版本是C函数.要在C ++源文件中声明它,您需要将其声明为

An additional complication is that the compilers perform "name mangling": the name they pass to the linker is a modified version of the source name. The C compiler may perform quite different name mangling from the C++ compiler. The standard lib version of atof() is a C function. To declare it in a C++ source file you need to declare it as

extern "C"
{
    double atof(const char *);
}

或可能

extern "C" double atof(const char *);

还有许多其他复杂性,但这足以继续进行下去.

There are many additional complexities, but that is enough to go on with.

最安全的想法是只包含适当的标题.

Safest idea is to just include the appropriate headers.

#include <iostream>
#include <cstdlib>

int main()
{
    const char v[]= "22";
    std::cout << "Cast result is " << atof(v) << std::endl;
    return 0;
}

额外的背景,以回复@DmitryFucintv的评论

  1. 通话约定

在调用函数时, 调用约定 有关如何在调用函数和被调用函数之间传递参数和返回值的信息.在x86架构上,最常见的两个是 __cdecl __ stdcall ,但还有许多其他的东西.

When calling a function, a calling convention is an agreement on how parameters and return values are passed between the calling function and the called function. On x86 architecture, the two most common are __cdecl and __stdcall, but a number of others exist.

请考虑以下内容:

/* -- f.c --*/

int __stdcall f(int a, double b, char *c)
{
    // do stuff
    return something;
}


/* main.c */

#include <iostream>
extern int __cdecl f(int a, double b, char *c);

int main()
{
    std::cout << f(1, 2.3, "45678") << std::endl;
    return 0;
}

在C程序中,这可能会编译并链接OK.函数f()期望其__stdcall格式的args,但我们以__cdecl格式传递它们.结果是不确定的,但很容易导致堆栈损坏.

In a C program, this will probably compile and link OK. The function f() is expecting its args in __stdcall format, but we pass them in __cdecl format. The result is indeterminate, but could easily lead to stack corruption.

由于C ++链接器有点麻烦,它可能会生成与您看到的错误类似的错误.大多数人都认为这是更好的结果.

Because the C++ linker is a bit fussier, it will probably generate an error like the one you saw. Most would agree that is a better outcome.

2名称处理

名称修饰(或名称修饰)是一种方案,编译器在其中添加了一些额外的字符 object 名称为链接器提供一些提示. object 可以是函数或变量.允许函数重载的语言(例如C ++和Java)必须执行类似的操作,以便链接程序可以区分具有相同名称的不同函数之间的区别. 例如

Name Mangling (or name decoration) is a scheme where the compiler adds some extra characters to the object name to give some hints to the linker. An object might be a function or a variable. Languages that permit function overloading (like C++ and Java) must do something like this so that the linker can tell the difference between different functions with the same name. e.g.

int f(int a);
int f(double a);
int f(const char *a, ...);

这篇关于标准C ++库链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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