来自
man gcc
:
-nostdlib
Do not use the standard system startup files or libraries when linking.
这里我们看到“链接时”。这意味着
-nostdlib
不会阻止 GCC 生成对 C 标准库函数的调用。
让我们检查一下:
$ cat t35.c
#define SIZE 4096
char b[SIZE];
void _start(void)
{
char *p = b;
int i = SIZE;
while(i > 0)
{
*p = 12;
++p;
--i;
}
}
$ arm-none-eabi-gcc t35.c -nostdlib -O2
ld.exe: cco83lvm.o: in function `_start':
t35.c:(.text+0x10): undefined reference to `memset'
在这里我们看到 ld 需要
memset
(因为 GCC 生成了 memset
)。因此,尽管用户的程序中没有 memset
,但用户仍需要提供 memset
。对于用户来说可能会感到困惑。
Clang 的故事相同:https://godbolt.org/z/jEz77fnf3。
总体问题很简单:
-nostdlib
不阻止GCC/Clang生成对C标准库函数的调用是否被认为是正常的?
UPD。为了防止生成某些 C 标准库函数,有一个
-ffreestanding
选项:
断言编译目标是独立环境。这意味着 -fno-内置。独立环境是标准库可能不存在的环境,并且 程序启动不一定在“main”处。最明显的例子是操作系统内核。这相当于 -fno-hosted。
演示:
$ arm-none-eabi-gcc t35.c -nostdlib -O2 -ffreestanding
<nothing> (expected)
-nostdlib 不会阻止 GCC/Clang 生成对 C 标准库函数的调用,这算是正常吗?
是的。该选项与链接和启动文件有关,而不是与优化有关。当您使用
-nostdlib
时,您通常会提供并链接到您自己的 memset
实现。
是的,这是有记录的。
memset
和其他一些是特殊情况。
https://gcc.gnu.org/onlinedocs/gcc-12.2.0/gcc/Standards.html#Standards
GCC 使用的大多数编译器支持例程都存在于 libgcc 中,但也有一些例外。 GCC 要求独立环境提供
、memcpy
、memmove
和memset
。最后,如果使用memcmp
,并且目标未实现陷阱模式,则 GCC 会发出对__builtin_trap
的调用。abort