RISC-V中局部初始化数组编译报memcpy未定义错误原因咨询
全局数组与局部初始化数组的编译差异原因分析
问题背景
我编写了一段C程序,初始版本中数组A、B为全局初始化数组,C为全局未初始化数组:
int A[size][size] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; int B[size][size] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; int C[size][size]; int multiplication() { //using array A, B and C here return 0; }
使用以下命令编译:
riscv64-unknown-elf-gcc -ffreestanding -march=rv32im -mabi=ilp32 -nostartfiles -nodefaultlibs -mno-relax crt0.s Myprogram.c -o Myprogram
编译过程正常,通过riscv64-unknown-elf-objdump -t Myprogram查看,数组A、B位于.data段,C位于.bss段。
但当我将数组A、B改为multiplication函数内的局部初始化数组后:
int C[size][size]; int multiplication() { int A[size][size] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; int B[size][size] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; //using array A, B and C here return 0; }
编译出现错误:undefined reference to 'memcpy'。为什么全局数组不会触发这个问题,局部初始化数组却会调用memcpy?
原因分析
全局初始化数组的处理逻辑:全局变量的内存空间在编译阶段就被分配到对应段——已初始化的进入.data段,未初始化的进入.bss段。对于A、B这类已初始化的全局数组,编译器会直接把初始化数据写入可执行文件的.data段,程序加载时操作系统会将这部分数据直接映射到内存中,不需要在运行时执行额外的复制操作,因此不会调用
memcpy。局部初始化数组的处理逻辑:局部变量是在函数调用时才在栈上分配内存的。对于带有初始化值的局部数组,编译器会先把初始化数据存储在程序的只读数据段(.rodata)中,等函数执行时,通过
memcpy将.rodata里的初始化数据批量复制到栈上的数组空间——这是编译器优化批量初始化操作的常规手段。而你编译时使用了-nodefaultlibs参数,没有链接标准库,memcpy作为标准库函数无法被找到,因此出现未定义引用的错误。
内容的提问来源于stack exchange,提问作者Sooora
相关产品推荐
相关产品推荐

