在 C 中更改数组值会产生“对‘memset’的未定义引用”

Tho*_*rio 2 c arrays gcc compiler-errors riscv

我正在初始化一个由 1 和 0 组成的 32 元素数组,作为 C 中生命游戏的起始状态。当我使用这一行时:

int board[] = {0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1,
               0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0};
Run Code Online (Sandbox Code Playgroud)

编译没有问题。但是,当我只是更改数组中的值,而不是数组的长度或声明时:

int board[] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0,
               0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
Run Code Online (Sandbox Code Playgroud)

该代码不会编译,而是生成“对‘memset’的未定义引用。”。这是我编译时遇到的错误:

[ubuntu@swell-dipper:~/OS/assiqnment2/c-and-assemblvA] $ make
riscv64-unknown-elf-gcc -O -march=rv32im -mabi=ilp32 -g -c main.c -o main.o
riscv64-unknown-elf-gcc -O -march=rv32im -mabi=ilp32 -g -c lib.c -o lib.o
riscv64-unknown-elf-as -march=rv32im -g -c calc_val.s -o calc_val.o
riscv64-unknown-elf-gcc -O -march=rv32im -mabi.ilp32 -g -c simulation.c \
  -o simulation.o
riscv64-unknown-elf-ld -nostdlib -o simulation -Map simulation.map \
  -T demo.lds crt0.0 main.o lib.o calc_val.o simulation.o
riscv64-unknown-elf-ld: main.o: in function 'main':
/home/ubuntu/OS/assignment2/c-and-assembly/q2/main.c:23:
  undefined reference to 'memset'
make: *** [Makefile:58: simulation] Error 1 
Run Code Online (Sandbox Code Playgroud)

完全相同的代码,只是数组元素具有不同的值,怎么可能无法编译?memset我也从未在任何地方的代码中使用过任何与 相关的内容。

我为数组的元素尝试了一些不同的值,无论代码是否编译,它都是打开和关闭的。

zwo*_*wol 5

ld自己在跑。这几乎总是一个错误。使用gcc“编译器驱动程序”进行链接,并从链接命令行中删除-nostdlibcrt0.o,问题就会消失。

发生的情况是编译器可能选择为第二个数组初始化生成代码,就像您编写的一样

int board[32];
memset(board, 0, sizeof board);
board[K] = 1;
Run Code Online (Sandbox Code Playgroud)

其中 K 是数组初始值设定项中单个 1 的位置。这是完全可以允许的;C 标准规定编译器可以生成对任何C 库函数的调用,即使它们没有出现在源代码中。您可以使用命令行选项使 GCC不太-ffreestanding愿意这样做,但它不会完全消除这些“合成”调用。 GCC手册的2.1节特别指出,即使在-ffreestanding模式下,它也可能生成对memcpymemmovememsetmemcmp

GCC 还可以生成对其自己的内部运行时库中的函数的调用,无论它是否处于独立模式。它们用于硬件不提供指令的算术运算之类的事情。

当您使用编译器驱动程序进行链接时,C 库、内部运行时库以及一些处理 C++ 全局构造函数等内容的“启动文件”都会自动包含在链接中,因此所有这些对您来说都是不可见的。使用ld绕过这一点并暴露了代码生成需要这些东西的事实,即使您认为不需要。原则上,您可以gcc -v使用查找所有额外隐式内容的名称,并仅添加回您需要的位,但几乎可以肯定,仅使用编译器驱动程序进行链接会更容易。