修改C语言数组值时出现‘undefined reference to memset’错误求助
生命游戏数组初始化引发的memset未定义引用问题
问题场景
为生命游戏初始化32个元素的int数组作为初始状态时,遇到了奇怪的编译问题:
- 以下数组初始化代码编译链接正常:
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};
- 仅修改数组元素值(保持长度和声明方式不变),以下代码编译时出现
undefined reference to 'memset'错误:
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};
编译链接的错误输出如下:
[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
问题原因
这是GCC编译器的自动优化行为导致的:
- 当数组初始化包含大量连续的0时,编译器会自动生成调用
memset的代码,用批量内存填充的方式代替逐个元素赋值,以减少代码体积、提升初始化效率。 - 你的链接命令使用了
-nostdlib选项,该选项会排除标准C库的链接,而memset是标准库中的函数,因此链接阶段找不到它的实现,报错"未定义引用"。 - 第一个数组的元素值分布零散,没有足够多的连续0,编译器判断逐个赋值的代码效率更高,因此没有生成
memset调用,所以编译链接正常。
解决办法
可以通过以下几种方式解决:
- 实现自定义memset:在你的
lib.c中手动实现一个简单的memset函数,比如:
void* memset(void* ptr, int value, unsigned int num) { unsigned char* p = (unsigned char*)ptr; while (num--) { *p++ = (unsigned char)value; } return ptr; }
这样链接时就能找到memset的实现。
- 禁用编译器的memset优化:在编译
main.c时添加-fno-builtin-memset选项,强制编译器不使用内置的memset优化,改为逐个初始化数组元素。 - 移除-nostdlib选项:如果你的运行环境允许链接标准C库,可以去掉链接命令中的
-nostdlib,让编译器自动链接包含memset的标准库(嵌入式场景通常不适用此方法)。
内容的提问来源于stack exchange,提问作者Thomas Mercurio
相关产品推荐
相关产品推荐

