在C中,什么构成“未定义的引用”?到一个符号?
我正在阅读有关 GCC 链接器的 --wrap
选项的 GNU 文档,该选项可用于模拟函数进行测试。
https://ftp.gnu.org/ old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html 表示以下内容:
--换行符号
对符号使用包装函数。任何未定义的符号引用都将解析为 __wrap_symbol。对 __real_symbol 的任何未定义引用都将解析为符号。这可用于为系统功能提供包装器。包装函数应称为 __wrap_symbol。如果它想调用系统函数,它应该调用__real_symbol。
我注意到它说任何对符号的未定义引用都将解析为 __wrap_symbol,但它没有说明对符号的未定义引用到底意味着什么。有谁具体知道什么是未定义?
我很困惑,因为我创建了一个成功模拟 read
函数的示例程序(它是用 gcc test.c -o test -Wl,--wrap=read
编译的启用模拟)。为什么链接器认为这个符号未定义?我包含了 unistd.h
,所以不应该定义 read
吗?我认为文档说 --wrap
仅适用于未定义的符号?
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define DUMMY_STR "I don't care because this function is mocked."
#define DUMMY_LEN (strlen(DUMMY_STR))
ssize_t __wrap_read(int fd, void *buf, size_t count)
{
sprintf(buf, DUMMY_STR);
return DUMMY_LEN;
}
int main()
{
char buf[128] = {'\0'};
puts("Press anything, then ENTER, to continue");
read(1, buf, sizeof(buf) - 1);
puts(buf);
return 0;
}
I was reading the GNU documentation on the GCC linker's --wrap
option, which can be used to mock functions for testing.
https://ftp.gnu.org/old-gnu/Manuals/ld-2.9.1/html_node/ld_3.html says the following:
--wrap symbol
Use a wrapper function for symbol. Any undefined reference to symbol will be resolved to __wrap_symbol. Any undefined reference to __real_symbol will be resolved to symbol. This can be used to provide a wrapper for a system function. The wrapper function should be called __wrap_symbol. If it wishes to call the system function, it should call __real_symbol.
I've noticed that it says Any undefined reference to symbol will be resolved to __wrap_symbol, but it doesn't say what exactly an undefined reference to symbol means. Does anyone know specifically what is considered undefined?
I'm confused because I created an example program that successfully mocks the read
function (it's compiled with gcc test.c -o test -Wl,--wrap=read
to enable mocking). How come the linker considers this symbol undefined? I included unistd.h
, so shouldn't that make read
defined? I thought the documentation said --wrap
only works on undefined symbols?
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define DUMMY_STR "I don't care because this function is mocked."
#define DUMMY_LEN (strlen(DUMMY_STR))
ssize_t __wrap_read(int fd, void *buf, size_t count)
{
sprintf(buf, DUMMY_STR);
return DUMMY_LEN;
}
int main()
{
char buf[128] = {'\0'};
puts("Press anything, then ENTER, to continue");
read(1, buf, sizeof(buf) - 1);
puts(buf);
return 0;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
包含头文件只是声明符号,它不会定义它们——它们在 test.c 编译单元中将是未定义,因为它从来没有定义过它们。
读取符号实际上是在 libc.so(C 标准库)中定义的,但是在链接程序时,它首先会看到您的编译单元 (test.o),此时读取仍然是 未定义。因此,对
read
的引用被映射到__wrap_read
。定义和声明是两个不同的东西。相关,但又不同。
Including the header file just declares the symbols, it does not define them -- they'll be undefined in your test.c compilation unit because it does not ever define them.
The read symbol is in fact defined in libc.so -- the C standard library -- but when linking your program it first sees your compilation unit (test.o) at which point read is still undefined. So the references to
read
are instead mapped to__wrap_read
.definitions and declarations are two different things. Related, but different.