提问:当我们编写了和库函数同名的函数,比如 strcmp,什么情况下会使用库函数版本的strcmp?什么情况下会使用我们自己编写的strcmp?
详细描述:我正在做 PA2.2 的蓝框题:为什么定义宏__NATIVE_USE_KLIB__之后就可以把native上的这些库函数链接到klib?
在 NEMU-native 中,可以通过是否定义宏 __NATIVE_USE_KLIB__ 来决定是使用库函数版本的string.h还是使用我们自己编写的klib版本的string.h。
为了解决这个蓝框题,我自己设计了一个小版本的代码app.c。在app.c中我自己编写了一个strcmp函数,并在main函数中调用它,如下图:
(app.c)的图片
但接着,我发现无论我怎么做,该代码都会调用库函数版本的strcmp,而对我自己编写的strcmp视而不见,如下图:
(结果)的图片
我感觉我同时遇到了两个问题:1. 我不明白gcc是怎样决定使用 库函数 还是 用户自定义函数 的。2. 我无法在自己编写的最小代码中使用自己编写的strcmp。
为了解决我的问题,我做了如下尝试:
1. 我在自己的最小代码中注释掉了 #include<string.h>,编译并运行后发现依然没有调用我的自定义strcmp函数
2. 阅读 NEMU 生成 string-native 可执行文件的Makefile过程,发现在链接的时候使用了 -lSDL2, -pie 和 -ldl 等选项,把这些选项应用到我编译app.c的过程中,
发现并没有用,程序调用的依然是库函数版本的strcmp
3. STFW。在Google上搜索 “c language how to override library function”
2.1. 查看stackoverflow网页“Overriding C library functions, calling original”。这个网页的提问几乎就是我想搞明白的 PA2.2 的蓝框题。
其中的最高赞回答说到:“链接器会先在‘命令行提供的文件’搜寻符号,然后再到库中搜寻符号,在所有平台上链接器都这样工作”。然而这个
回答对我而言没有用,因为在我编译app.c的时候,显然链接器并没有选择我自己编写在app.c中的strcmp,而是选择了库函数的strcmp
第二个回答提到了使用 -ldl 选项,在用户自定义函数中使用 dlsym 来调用库函数中的同名函数。这个回答有用的前提是我已经能够调用
我自己编写的strcmp,因此这个回答对我没有用。
其它的回答并没有解决我的问题。
2.2. 查看了一些别的相关网页,它们提供的方案主要是是使用类似 #define strcmp my_strcmp的宏,或者是在链接时使用 --wrap,这两种
方法都不是NEMU-native使用的方法,并且我个人认为对我的app.c的问题也没什么用。
4. 我使用 gcc -Wl,--verbose 编译了app.c以试图观看链接过程,洪水流一般的输出对我而言没有意义,我尝试匹配字符串string,没有搜到任何匹配的模式。
我依然无法解决我的问题,请问有人能给我任何建议或者提示嘛?
(尝试了一下,使用g++的时候是可以的,也许是因为C++提供了重载函数功能)
-----------答案在这里------------
gcc 编译时 使用 -fno-builtin 选项就可以使用自己编写的库函数同名函数