精华内容
下载资源
问答
  • // test.c #include<stdio.h> #include<math.h> ...double fabs(double x) //绝对值函数,这个函数与math.h中的fabs函数同名 ...double sqrt(double a) //开...不理解与math.h中的函数同名了,为什么不报错
  • C/C++多个链接库含有同名函数,编译会报错吗起因基本概念同名函数测试测试1:`.o`目标文件测试2:静态库测试3:动态库同名函数的应用 起因 由于业务需要,我司使用了Mellanox某闭源C++程序,Mellanox推荐的定制化...


    起因

    由于业务需要,我司使用了Mellanox某闭源C++程序,Mellanox推荐的定制化开发方法是:对其链接的动态库进行定制化开发,以添加额外的功能。

    在方案讨论阶段,发现很多同事对动态库/静态库所代表的的含义并不十分清楚,特别是当同名函数存在时,编译、链接、运行的结果是什么也没有明确的认识,故写下这篇文章。

    基本概念

    程序函数库可分为下面几种类型:

    1. 静态函数库(static libraries):在编译期间(compile-time)静态链接库会全部拷贝进编译对象中,一般以.a文件的存在
    2. 动态函数库(shared libraries):在程序启动的时候加载到程序中,它可以被不同的程序共享,一般以.so文件存在
      • 动态加载函数库(dynamically loaded libraries),在进程运行期间,使用dlfcn.h中的函数加载、调用、关闭动态库

    关于动态库和静态库的优缺点,相关文章很多,这里不再赘述

    同名函数测试

    使用两个.c文件test2.ctest2.c包含同名函数void test()

    // test1.c
    #include <stdio.h>
    
    void test() {
        printf("call from test1.c");
    }
    
    // test2.c
    #include <stdio.h>
    
    void test() {
        printf("call from test2.c");
    }
    

    含有main函数的文件main.c

    // main.c
    extern void test();
    int main() {
        test();
    }
    

    测试1:.o目标文件

    使用如下命令行,将test2.ctest2.c生成目标文件,并编译可执行文件

    gcc -c ./test1.c
    gcc -c ./test2.c
    gcc -o main ./test1.o ./test2.o ./main.c
    

    结果报错:

    ./test2.o: In function `test':
    test2.c:(.text+0x0): multiple definition of `test'
    ./test1.o:test1.c:(.text+0x0): first defined here
    collect2: error: ld returned 1 exit status
    

    可见,将包含同名函数的目标文件进行链接,如果其在同一个命名空间中,会报multiple definition错误。

    测试2:静态库

    使用如下命令行编译静态库libtest1.alibtest2.a

    g++ -c ./test1.c
    g++ -c ./test2.c
    ar crv libtest1.a test1.o
    ar crv libtest2.a test2.o
    

    接着我们链接编译:

    gcc -L. ./main.c -ltest1 -ltest2 -o main
    

    可以编译成功,无报错。执行结果如下

    $ LD_LIBRARY_PATH=. ./main
    call from test1.c
    

    有朋友会问:“为什么没有报错呢?我明明把包含同名函数的两个静态库链接进同一个可执行文件了。”

    为了探究为什么没有报错,我们增加ld选项-Wl,--verbose来看看链接时到底发生了什么。再执行编译,我们得到输出:

    ...
    
    attempt to open ./libtest1.so failed
    attempt to open ./libtest1.a succeeded
    (./libtest1.a)test1.o
    attempt to open ./libtest2.so failed
    attempt to open ./libtest2.a succeeded
    
    ...
    

    可以发现,最终的链接结果,输出的二进制文件只链接了libtest1.a背后的test1.o文件,而没有链接libtest2.a。编译器这么做的含义是:

    1. 编译器根据链接先后顺序,依次查找链接库。
    2. 首先查找libtest1.a,发现其有main函数需要的函数void test(),因此将其进行了链接。
    3. 再扫描到libtest2.a的时候,由于void test()已经被libtest1.a中的符号提供,因此不再链接。

    Stack Overflow中有个问题也谈到了这点。

    如果使用ld参数--whole-archive强行链接libtest1.alibtest2.a,我们会看到和测试1同样的报错:

    $ gcc -L. ./main.c -Wl,--whole-archive -ltest1 -ltest2 -Wl,--no-whole-archive -o main
    ./libtest2.a(test2.o): In function `test':
    test2.c:(.text+0x0): multiple definition of `test'
    ./libtest1.a(test1.o):test1.c:(.text+0x0): first defined here
    collect2: error: ld returned 1 exit status
    

    测试3:动态库

    使用如下命令行编译动态库libtest1.solibtest2.so并编译可执行文件。

    gcc -shared -fPIC -o libtest1.so test1.c
    gcc -shared -fPIC -o libtest2.so test2.c
    gcc -L. ./main.c -ltest1 -ltest2 -o main
    

    编译无报错,ldd检查,libtest1.solibtest2.so确实都链接进main可执行文件中。执行结果如下:

    $ LD_LIBRARY_PATH=. ./main
    call from test1.c
    

    可见,在动态链接时,不同的链接库可以有同名函数,不影响编译。这是由动态链接库的性质决定的,其只有在运行时才会动态加载,并且加载的顺序是由编译时链接的顺序决定的。这也就说符号会以第一个查找到的为准(Symbols are resolved on a first match basis)。

    我们也可以通过设置LD_PRELOAD提前将某动态库load进内存

    同名函数的应用

    有朋友会提出这样的疑问,上面虽然做了这么多实验,但多少有点语言律师的感觉,这些知识能改善我们日常生活吗?日常工作中能用的到吗?答案当然是能用得到。

    最简单的应用场景,比如某开源库中有个函数我不喜欢,我想写个自己的版本替换掉,那么完全可以利用上述的知识,将自己实现的某函数以动态或者静态的方式链接进可执行文件中,替换自己不喜欢的版本。

    工业上常见的应用有以下几种:

    1. 替换库:大名鼎鼎的tcmalloc就是以这种方式运行的。我们将tcmalloc链接进程序,只要tcmalloc库的查找顺序优先于libc,就可以替换原生的内存管理函数为tcmalloc版本。
    2. mock测试:陈硕在文章中详述了如何在C++单元测试中mock系统调用。其中的链接期垫片 (link seams)方法,就是利用libc一般情况下是动态链接的特性,在进程中mock系统调用。
    展开全文
  • python导入两个包括同名函数的模块

    千次阅读 2019-02-27 18:01:30
    当使用的函数中出现同名函数时,如果不注意的话,会造成程序的异常,这个时候要仔细的看程序的报错信息,会发现是函数的引用出现错误。如果不仔细的话会误以为是其他原因导致函数不能正常运行,会浪费很多时间。o(╥...

    当使用的函数中出现同名函数时,如果不注意的话,会造成程序的异常,这个时候要仔细的看程序的报错信息,会发现是函数的引用出现错误。如果不仔细的话会误以为是其他原因导致函数不能正常运行,会浪费很多时间。o(╥﹏╥)o

     

    rectangle和 circular为两个不同的模块,它们都包含girth函数

    如下运行函数时会有异常

    from rectangle import *    #导入矩形模块
    
    from circular import *      #导入圆形模块
    
    girth(10)                      #调用计算圆形周长的函数
    
    girth(10,,20)           #调用计算矩形周长的函数

     

    解决办法是:不使用from....import 导入,而是使用import导入

    import rectangle as r
    
    import circular as c
    
    c.girth(10)                      #调用计算圆形周长的函数
    
    r.girth(10,,20)           #调用计算矩形周长的函数

     

    也可以直接把函数起别名,这样在用函数的时候直接使用函数别名就行了

    from... import ....as...

    展开全文
  • 在Java中如果一个类同时继承接口A与B,并且这两个接口中具有同名方法,会怎么样? 会报错 若函数名不同(包括传入参数但包括返回值类型),则不会报错 ...

    在Java中如果一个类同时继承接口A与B,并且这两个接口中具有同名方法,会怎么样?
    在这里插入图片描述
    会报错
    若函数名不同(包括传入参数但不包括返回值类型),则不会报错

    展开全文
  • C++ 调用父类同名函数

    千次阅读 2014-03-13 22:08:27
    1、子类和父类函数签名一致,有virtual关键字,根据调用对象类型判断调用的父类还是子类的函数 ...3、子类和父类函数参数,函数名一致,返回类型一样,若没有virtual关键字同2,有virtual关键字会报错

    1、子类和父类函数签名一致,有virtual关键字,根据调用对象类型判断调用的父类还是子类的函数


    2、子类和父类函数签名一致,没有virtual关键字,父类函数被隐藏,需要使用  父类::函数名 强制调用父类函数


    3、子类和父类函数参数,函数名一致,返回类型不一样,若没有virtual关键字同2,有virtual关键字会报错


    展开全文
  • 看下面代码,编译会不会报错,如果不报错,执行的结果是啥? using System; class Program { static void Main(string[] args) { ...
  • Python报错

    2020-05-24 21:55:12
    前言 这里主要为了记录python遇到的一些比较...最常见的情况就是函数和变量同名了,使得调用函数时(call),系统会误认为这是在调用变量,造成错误(变量不会callable) 问题解决 找到和内建字符重名的函数,然后重新
  • C++ 全局函数与全局变量同名 C++中相同作用域的函数和变量同名 // 编译报错 int a = 10; void a(){ // some code} 某日,在Chromium源码中看到如下代码。咋一看,以为函数与变量同名了,...
  • pytesseract报错

    2020-05-23 10:50:17
    AttributeError: module ‘pytesseract’ has no attribute ‘image_to_string’ 问题是,您必须将python文件重命名为其他名称,而不是pytesseract.py。您的python文件与tesseract内置函数同名
  • printf("你建立的链表合法,请重新建立"); input(2); } break; } } ``` 该项目只写了这2个文件。下面上张报错的图: ![图片说明]...
  • Python全局变量报错

    2020-03-13 10:00:16
    内部函数修改全局变量但可以访问全局变量 内部函数,修改同名全局变量,则python会认为它是一个局部变量 在内部函数修改同名全局变量之前调用变量名称(如print sum),则引发Unbound-LocalError import sys ...
  • 但是最后出现函数不在作用域的错误。 这是我的configure <p>./configure -opensource -confirm-license -release -shared -nomake examples -nomake tests -no-opengl -no-qt3d-profile-jobs -qt3d-profile-gl -no...
  • 结果导致报错:调用函数的那一行对象支持此属性。 找了很长时间都找不出原因,开始的时候一直以为是写错了某个字母,才发现js函数根本没有执行。后来没有办法直接调用了别的函数,发现就有用了,认为是函数名的...
  • Flask函数无法调用

    千次阅读 2019-11-10 17:24:59
    一.序言 初学python和flask的同学,可能会遇见这样的问题,我在python无法调用函数,在flask中无法调用函数。 二....场景一:一般的函数调用 报错:name’test’ is...场景三:同名函数调用 结果没有报错,而是:调用...
  • 今天在做深圳茁壮网络公司的笔试题时遇到一个令我非常困惑的问题,在网上找了好久没有找到满意的答案,所以只好自己总结下,如果写得有错误,希望大家...编译器还不报错,无语..... 我加了很多的printf来测试,发...
  •   一个页面中定义两个同名的JS函数,调用会是什么结果,可以平时写程序都还小心,都没有碰以过,后面尝试了一下不报错,会调用第二个方法;
  • python程序报错Error:'int' object is not callable解决方法

    万次阅读 多人点赞 2018-08-18 20:09:20
    报错 XXX is not callable时,是因为代码调用了一个能被调用的变量或对象。具体而言,可能是调用了错误的函数和变量。易错情况就是函数和变量同名了,使得调用函数时,系统会误认为这是在调...
  • 同时添加两个引用会导致由于有两个同名datetime模块,调用datetime模块函数时程序知道调用的是哪一个而报错,from datetime import datetime是import datetime的子模块 解决方案: 将from datetime import ...
  • 今天发现,封装在私有库中的文件中有一个C语言方法,在项目中一个文件中同样定义了一个同名的C语言方法 导致因C语言方法重名导致报错。 原因:c语言没有namespace,即使在不同文件中,方法也能重名。 解决方案...
  • es6 - 函数 扩展

    2019-03-20 19:53:00
    1. 可添加默认参数 function fn(name,age=17){ console.log(name+","+age); } fn("Amy",18); // Amy,18 f n("Amy",""); // Amy, ...注意点:使用函数默认参数...但是不使用默认参数时,多个同名形参不报错。 只有...
  • JavaScript支持函数重载

    千次阅读 2014-02-27 20:05:41
    但是有趣的是Javascript并支持函数的重载,如果像Java那样写出函数重载Javascript并报错,这就是有趣的地方了---支持但又不算错误。那么对于同名函数,当调用时只是简单的调用最后一个函数,就像是最后的...
  • 在 python 的函数中定义了和全局变量同名的变量,如果在函数中修改这个变量的值,python 就会认为它是局部变量,在函数中对这个变量的引用自然就会被认为是没定义。 如果确定要在函数中引用全局变量,并且要对它...
  • 内部函数修改全局变量可以访问全局变量 内部函数,修改同名全局变量,则python会认为它是一个局部变量 在内部函数修改同名全局变量之前调用变量名称(如print sum),则引发Unbound-LocalError 在程序中设置的...
  • 发现 <code>get_lib_path</code> 函数会拼接一个后缀为 <code>.a</code> 的路径,后续在检测到该路径存在时报错了</li><li>问题: 个人理解<code>SDWebImage</code> 是被打包成了 framework,在...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 271
精华内容 108
关键字:

同名函数不报错