You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust avr_hal项目使用libc_alloc时链接失败的问题求助

AVR-Hal项目Cargo构建链接错误问题解决

问题描述

在对avr_hal项目执行cargo build时,抛出链接错误:

error: linking with avr-gcc failed: exit status: 1

完整错误信息:

WARN rustc_codegen_ssa::back::link Linker does not support -no-pie command line option. Retrying without.
error: linking with `avr-gcc` failed: exit status: 1
  |
  = note: LC_ALL="C" PATH="/usr/local/rustup/toolchains/nightly-2023-08-08-x86_64-unknown-linux-gnu/lib/rustlib/x86_64-unknown-linux-gnu/bin:/vscode/vscode-server/bin/linux-x64/74f6148eb9ea00507ec113ec51c489d6ffb4b771/bin/remote-cli:/usr/local/cargo/bin:/usr/local/cargo/bin:/usr/local/cargo/bin:/usr/local/cargo/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/home/vscode/.local/bin" VSLANG="1033" "avr-gcc" "-mmcu=atmega328p" "/tmp/rustcfZfdOa/symbols.o" "/workspaces/avrgcc_linking_fail_mre/avrgcc-linking-failed-mre/target/avr-atmega328p/debug/deps/avrgcc_linking_failed_mre-4f3e20c93dc596f3.arduino_hal-6541d5c2c9fe98bb.arduino_hal.fa13f7103336eb93-cgu.0.rcgu.o.rcgu.o" "-Wl,--as-needed" "-L" "/workspaces/avrgcc_linking_fail_mre/avrgcc-linking-failed-mre/target/avr-atmega328p/debug/deps" "-L" "/workspaces/avrgcc_linking_fail_mre/avrgcc-linking-failed-mre/target/debug/deps" "-L" "/usr/local/rustup/toolchains/nightly-2023-08-08-x86_64-unknown-linux-gnu/lib/rustlib/avr-atmega328p/lib" "-Wl,-Bstatic" "/workspaces/avrgcc_linking_fail_mre/avrgcc-linking-failed-mre/target/avr-atmega328p/debug/deps/libcompiler_builtins-400b15d51260279e.rlib" "-Wl,-Bdynamic" "-lgcc" "-Wl,-z,noexecstack" "-L" "/usr/local/rustup/toolchains/nightly-2023-08-08-x86_64-unknown-linux-gnu/lib/rustlib/avr-atmega328p/lib" "-o" "/workspaces/avrgcc_linking_fail_mre/avrgcc-linking-failed-mre/target/avr-atmega328p/debug/deps/avrgcc_linking_failed_mre-4f3e20c93dc596f3.elf" "-Wl,--gc-sections"
  = note: /workspaces/avrgcc_linking_fail_mre/avrgcc-linking-failed-mre/target/avr-atmega328p/debug/deps/avrgcc_linking_failed_mre-4f3e20c93dc596f3.arduino_hal-6541d5c2c9fe98bb.arduino_hal.fa13f7103336eb93-cgu.0.rcgu.o.rcgu.o: In function `_$LT$libc_alloc..LibcAlloc$u20$as$u20$core..alloc..global..GlobalAlloc$GT$::alloc::hcb8d6e5a6803e71c':
          /usr/local/cargo/registry/src/index.crates.io-6f17d22bba15001f/libc_alloc-1.0.5/src/lib.rs:35: undefined reference to `memalign'
          /workspaces/avrgcc_linking_fail_mre/avrgcc-linking-failed-mre/target/avr-atmega328p/debug/deps/avrgcc_linking_failed_mre-4f3e20c93dc596f3.arduino_hal-6541d5c2c9fe98bb.arduino_hal.fa13f7103336eb93-cgu.0.rcgu.o.rcgu.o: In function `alloc::raw_vec::finish_grow::h0af711d7dce70706':
          arduino_hal.fa13f7103336eb93-cgu.0:(.text._ZN5alloc7raw_vec11finish_grow17h0af711d7dce70706E+0xb2): undefined reference to `memalign'
          collect2: error: ld returned 1 exit status
          
  = note: some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
  = note: use the `-l` flag to specify native libraries to link
  = note: use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)

复现步骤

  • 安装cargo-generate:执行 cargo install cargo-generate
  • 生成avr-hal项目:cargo generate --git https://github.com/rahix/avr-hal-template.git --name avrgcc-linking-failed-mre(选择Uno开发板)
  • 添加.cargo/config.toml配置文件:
    [build]
    target = "avr-specs/avr-atmega328p.json"
    
    [unstable]
    build-std = ["core", "alloc"]
    
  • 修改src/main.rs内容:
    #![no_std]
    #![no_main]
    
    use libc_alloc::LibcAlloc;
    use panic_halt as _;
    
    extern crate alloc;
    
    
    #[arduino_hal::entry]
    fn main() -> ! {
        "123".replace("1", "4");
        loop {}
    }
    
    #[global_allocator]
    static ALLOCATOR: LibcAlloc = LibcAlloc;
    
  • 在Cargo.toml依赖中添加:libc_alloc = "1.0.5"
  • (可选)使用开发容器的话,添加.devcontainer/devcontainer.json:
    {
        "name": "avrgcc_linking_fail_mre_devcontainer",
        "dockerFile": "Dockerfile"
    }
    
  • (可选)添加.devcontainer/Dockerfile:
    FROM mcr.microsoft.com/devcontainers/rust:1-1-bullseye
    
    RUN apt update
    
    RUN apt install -y fish
    RUN apt install -y avr-libc gcc-avr pkg-config avrdude libudev-dev build-essential
    
    RUN cargo install cargo-generate
    
  • 构建开发容器后,进入项目目录执行cargo build或cargo build --release触发错误

问题成因

错误核心是undefined reference to memalign:

  • libc_alloc crate依赖标准libc中的memalign函数实现内存分配,但AVR平台的avr-libc并未提供该函数
  • AVR属于资源受限的嵌入式平台,其libc仅实现了基础内存分配函数(如malloc、free),没有memalign这类对齐分配的函数,导致链接时找不到对应符号

修复方法

方法1:使用AVR专用全局分配器

替换libc_alloc为适配AVR的分配器,比如avr-alloc:

  1. 移除Cargo.toml中的libc_alloc依赖,添加:
    avr-alloc = "0.2.0"
    
  2. 修改src/main.rs,初始化AVR堆并设置全局分配器:
    #![no_std]
    #![no_main]
    
    use avr_alloc::AvrAlloc;
    use panic_halt as _;
    
    extern crate alloc;
    
    #[global_allocator]
    static ALLOCATOR: AvrAlloc = AvrAlloc;
    
    #[arduino_hal::entry]
    fn main() -> ! {
        // 初始化堆:指定堆的起始地址和大小
        // 对于Atmega328p,SRAM总大小2KB,这里预留部分给栈,设置堆大小1KB
        unsafe {
            avr_alloc::init_allocator(0x800200, 1024);
        }
    
        let _modified_str = "123".replace("1", "4");
        loop {}
    }
    

方法2:使用无动态分配的替代方案

AVR资源有限,动态内存分配易引发碎片化问题,推荐使用heapless crate提供的固定大小容器:

  1. 添加heapless依赖:
    heapless = { version = "0.8", features = ["alloc"] }
    
  2. 修改代码使用heapless::String替代标准库字符串:
    #![no_std]
    #![no_main]
    
    use heapless::String;
    use panic_halt as _;
    
    #[arduino_hal::entry]
    fn main() -> ! {
        let mut s: String<32> = "123".into();
        s.replace_range(0..1, "4");
        loop {}
    }
    
    这种方式无需全局分配器,更适配AVR这类嵌入式设备。

关于AVR-Hal中使用全局分配器

可以使用,但必须选择适配AVR架构的分配器实现,不能直接使用针对桌面/服务器libc的分配器(如libc_alloc)。AVR的内存模型与标准系统差异较大,需要使用专门为其编写的分配器,或自行基于AVR的SRAM实现简单分配逻辑。

内容的提问来源于stack exchange,提问作者cico

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 23:05:55